 Hi everyone, this is Pratik Jaiswal and I work as a Frontend developer at Zeta. I'm here to give a talk on building scalable view web apps for multiple instances. These days, many companies are moving to multiple countries, especially startups in the recent times. With this, it comes as a challenge to us Frontend developers to design a web application in such a way so that it's easy to scale, develop and deploy. I came across the same situation where I need to build an application, scales into multiple countries. And these challenge here is much more than language, currency or time zone because it can be satisfied by the I-18 library. Here the challenge comes is that in multiple countries, the logic and flow can be different. But more or less for one application, it will be more or less the same. Consider a mobile web application where you have a user profile. In that case, most of the part will behave similarly. Only few part might change based on the country. Example, in India, in the profile page, in case of Fintech, might have a KYC component. But in any other country, in Brazil or etc., you won't have that component. So we need to manage these conditions. A single repository, the aim was let's see how we were able to achieve it. So what are the options I had that time? The first option is the first easiest option which comes in our mind and the safest one is to maintain different repositories. But it's obviously not a good practice because you're maintaining multiple shadow copies of the same repository and consider a situation when there's a security fix you need to do or you need to change the scroll behavior. You'll need to make multiple developments and multiple releases. It's a huge task. The other approach was like most of the developer which we all follow is Eiffel's approach. It's maybe because of the bandwidth we have, we go with this approach of Eiffel's. This may work out for you for like one or two countries but consider a situation when you have more than five, six countries. It'll make the code look very dirty. Not even this. You will be shipping the code, everything in one bundle of multiple codes of different countries in the single bundle. And also if one developer is introducing a bug in one country, it'll go in multiple countries. So obviously this was not another approach we should go for. One more neat approach was maintaining configurations. This is an enhancement over the Eiffel's conditional statements but again if you have like five, six countries then the backward compatibility becomes very difficult to maintain if you have configurations. Consider the situation you are the like sixth country, the person who is developing and you are making some change. Imagine you have to change the configuration, you have to go to each and every country developer to know what impact it will make to your country. This required a lot of team interaction and this again was not a solution we went for. The last is one of the developers shared with me. In this case what he was doing is he was trying to change the resource path during the deployment. This solution can help you switching the countries but not avoiding duplicate code. So let's see what are the principles which our solution is following. We'll prevent any kind of duplicate code in our solution, separation of concern. So here we'll build separate country folder for each country so that one country team is working on a specific folder they won't mess with any other country folder and also it will avoid a lot of conflicts in inheritance. We'll use maximum reusability in this approach and only we'll override the country specific requirements in our country modules. We'll only load the required code. We won't load any of the code of any other country. Our testing and deployment will be independent. So as a developer we focus on making the development experience better but also a major part comes in testing and deployment because one country team will be waiting for hours at night to release but other country should not be dependent on them. Every release should be separate of each country. These are the challenges which we thought we should solve. Make this complete framework, building scalable web apps for multiple countries work out. This is the core of the solution. You make sense. You make sense are very powerful. Here you can even have the component options like data, methods, components, props inside the Vmix and itself. Not even this. You can even have life cycle hooks inside the mix and so in my case I had an application already developed and I had to scale it to like I was the person who was implementing the third country. The other guy for them conditional configurations worked out but for me again going and working on it was not a good idea for me. So what I did, this helped me to move the complete JavaScript code of the Vmixin into a Vmixin, JavaScript code into a mixing completely. As I said that Vmixins are a little debatable but yes Vmixins are smart. Here for a specific use case if you are using with proper documentation it will give you good results. Let's see how Vmixin looks like. So here we can see we have defined a mixin and inside the mixin we are having the component option of methods. Here we are defining a foo method and a conflict method. The view instance we can see that we are importing this mixin and we are defining a new function called bar and then again we are overriding the existing function conflict and if you are printing it we can see foo is printed from the parent, bar is implemented from a child and conflicting is overriding the parent. This feature will help us defining the country specific requirements and also we will be using JavaScript's ES6 dynamic imports with dynamic expressions and web code printing. This will help us separate each country fold as a separate chunk and loading the specific chunk while we are loading the application or while we are building the application. You can see the format. Here we are passing the country ID. This can come from the webpack variable or it can come from dynamically. It will automatically load respective modules with dynamic imports. Now let's see how folder structure will look like. So here we can see that each country module is having a separate folder and each country folder has an app body. This separation of concern will help us avoiding conflicts and each team will work on its folder without disturbing any other country. Every country here is having an app body. Let us see how the app body looks like. The app body we are having components. So these components will be across various countries. Most of them will be reusable. But in case if we have a separate component based on a specific country example, as I mentioned, in case of India you will need to have KYC. We will use the KYC component here but it might not be used in the case of any other country. So we will define the components which we use and most of it will be reusable. It will be used in multiple countries. So this is the mixing code. So this will be the complete functionality of that module. Here we can see we are having data, methods, components and mount. Imagine everything is different inside the mixing. It just looks like a component JavaScript. And then again, here you can define the functionality if we have much more than language, currency or time zone. So this will be the base component which will import in our country. So here we can see this was the user profile component. We are importing the user profile mixing which has a complete functionality and we are overriding it with the country specific requirement which we have. Here we can see in our case, example if we are in Vietnam, the country code will be different. The theme code which we are injecting might be different. Also the functionality, the function and even the API call if it's different, we will override that function here and we will take the country specific implementation based on the requirement. And imagine this same mixing will go in multiple countries. We are using the same mixing for n number of countries. See how we are avoiding so much of duplicate. So this is how our overall component looks like. We can see we have a lot of reusable common components like the user name field, user email field and phone field. These will be used in multiple countries. JavaScript as we discussed, we are importing the same mixing in multiple countries and only writing the country specific implementation. Not even the templating and the scripting. Even in the styling we can see, we have defined the common style all at one place and we are importing it and we are overriding in our country specific child component. So we will have the basic component in the parent folder in the common modules folder. We will use that if we don't have any changes. If you have a country specific requirement, we will define it adjacent to the app body and we will use import that component instead. And that component will import the complete JavaScript from the mixing styles again. And only we will specify the country specific requirement inside this component. You can see we are doing so much of reusability. Only we defined at one place and then only overriding in the country specific. So this is the part which will make sure that each of the country specific app bodies are loaded based on maybe the webpack variables or dynamically specifying the country. So in the last line we can see the app body. We are importing the country ID. This country ID is coming from the webpack variable and we can have, we can define a mapping of webpack variable and the folder name. And then again we have an else, it might be helpful for you in the testing where you can just specify with the parameter which country module you want to load and dynamically that country module will be loaded. And this will also ensure that when we are building, we are only building for a specific country. So we saw how we made the development experience seamless and we chunked out all the countries into specific country chunks. During the deployment we will create separate pipelines for each country making it sure that each country is not affecting any other country. Here we can see when we will build such kind of an application we will get multiple region modules like region 1, 2, 3. This is how dynamic import works. Whenever you specify a path it will create chunk for each of the folder or the component inside that path. But it will only include the component which we are specifying in the webpack variable. If you are using the US module it will only include the US module when you are running the application. And we saved so much of other country code as we are not including it in our build. So here we saw this use case of building a scalable web app for multiple countries for instances. And here we used feature of view and JavaScript and no other library to make it possible. We followed the principles. We are not making any code duplicate. We are using maximum reusability. We are doing inheritance. We are maintaining the separation of concern each country is having a separate module avoiding conflicts. We are only loading the code which is required with dynamic imports. And major thing the testing and the deployment is independent of each other. The testing team of one country only needs to work the other. Testing team can relax and not concern with the release happening in the other country. Yes. Because the approach which I followed to make it possible making one repository work out for multiple countries with the seamless development experience and also the testing experience and the deployment experience. So we have time for a few questions. Yeah. Hi. So in our organization we use Ember JS and actually using Mixins and Ember you had some pretty bad experiences. So Ember Mixins can actually access the attributes of the components that it is imported into. So if the developers are not careful and they assume that say the store object is available. It can actually lead to a crash when you imported somewhere else. So my question is why Mixins are the only solution for reusability problems. Like why can't you use a traditional helper. So at least you know like what is the data that is expected in the helper and what it is returning. So as you said Mixins yeah. But yes again the slide if you read Adios by the person mentioned in the Orioli article that Mixins if you're using it with a little documentation. It can help you identify which function is being implemented. And if you consider our situation you gives the power to include the complete component options and then lifecycle hooks inside the Mixins. And in our case it is one level of overriding. So one is the base component and other countries which are overriding it. So when we go to the country component we know that if we're not overriding it's from the parent component. If you're overriding it's from our parent component. This worked out pretty well for us. In case you have one parent and one child. Hey nice talk Praveen here. So I have question as in where would a library like Vue I18N or any library that allows you to do translations. Where would it fit in all the architecture that you have talked about. So when this requirement came we thought that this will include the Vue I18 library. Translations will be done in time. But when product manager came it said that come on they don't have a KYC in Brazil. Some other country. So then we went with this architecture. And answering your question I18 will include it in the base application. All the templates will include the Vue I18 tags inside the templates. And every component will follow the Vue I18 tags. So automatically the translation will be done. So what we can do is in the time of initialization as we saw. The way we are setting theme in the mount application we can set the language. Better approaches. When you are initializing the Vue component you are passing the I18 inside that. When you are initializing the I18 library there you can specify the local which can come from the parameter. Maybe you can define a configuration for that based on the webpack variable you are importing. How is it different from a Vue Async component? So in this case you actually used a mixin. But let's say you have inheritance based different components. And you asynchronously load one of the child components. How different is that going to be with this? So the reason yes we used mixins here was one is the usability of an inheriting of the parent component. And also we are having the Vue component options of data methods everything inside it. So in my case the repository was already ready. What I had to do is to make it scale in different countries. So what I did when I came across the mixins I saw that they are giving the power to include the complete component option. And not only this if you are if you are using this you will import the same mixin in multiple countries will override it. In case of component you might get duplicate quotes. But from my experience you can still do the same thing with you know inheritance hierarchy of components itself. So if you see the JavaScript part and the styling part we are quoting both of them and then overriding it. We are defining it at one place and then quoting it and overriding it. In case if you are creating multiple components you might have duplicate styling duplicate JavaScript component as well.