Building Large-Scale Vue.JS Application

Introduction on Vue.JS

Recently I have talked about Frontend DevOps, couple of people approched me and showed their interest in a more detailed explanation. This time I want to share my experience based on a project I am working on, which is in fact large-scale Vue.JS application, the challenges it throws at you, mistakes that could be avoided.

Vue.JS was a new player in a game at the point when we started developing our application, but it was rapidly growing, had great community support, amazing documentation and a lot less steep learning curve than other alternatives on the market. Learning curve was one of the main reason for picking it up, developer who did not had experience with advanced JavaScript could still deliver decent quality code without spending a lot of time on learning.

Magento (or simply, backend)

We are using Magento as a base platform, but in general it does not matter what is used on the backend. All we need is API that will provide required information to our Vue.JS application.

Single Entry Point per page

We decided not to build single page application. Could we choose otherwise? Definetely, but the final product at the very beginning was not completely clear and we decided not to overcomplicate, especially when vue-router did not had stable version released so we stick with multi-page application. What that mean is that we have only one entry template that connected to Magento for each page where we define parent Vue component that afterwards generate layout for that page.

Direct DOM manipulation (or simply, jQuery)

Sometimes we use jQuery, it still saves us some time when we are working with animation, however I would get rid of it completely, people will definitely abuse it. The reason behind dropping it is plain and simple, jQuery is a DOM driven and Vue.JS is DATA driven. It is a key difference, we do not want at any point to do direct DOM manipulations, we always want to work with data. Direct DOM manipulation will lead to lose of two-way binging and as a result to unpredictable behaviour of the application.

Inheritance and Abstraction

There is multiple ways how we mange modularity of our application. Two of them provided by Vue.JS framework and the third one is a native JavaScript solution.

Mixins

When we want to reuse parts of our component we are creating mixin, it follows the same declaration rules as a regular component, however it does not actually creates an instance of a component, it just adds (mixes in) portion of functionality that we abstracted. Components also not limited to a single mixin and can be extended with multiple ones if that is required.

Extend

Extend behaves similar to mixin, but uses classical inheritance model. You cannot use multiple extends in a single component and it will extend entire component creating its own instance. It is useful to use when we have multiple applications that have almost the same functionality (just some minor adjustments) because of layout changes for example.

Export

Export/import is something that we are using all the time. We are abstracting filters, animations, utility functions, we are importing local components instead of declaring them globally. It just a perfect tool for making your code modular.

Tools

vue-cli

It is a great tool for scaffolding Vue.JS application. You can generate different setups of the project and play around with the example app before you making final decision on how you want your own build to look like. It includes linters, tests, bundling, etc.

Vuex

Vuex flowVuex flow

I cannot stress enough how important is to use Vuex. Basically Vuex is global data storage. If there is something that you know will be shared across multiple components, you will put it there. This will make sure that all the data inside will be always synchronised. As soon as something gets changed in Vuex it will notify all dependent components about those changes and your application will behave accordingly. Our initial implementation was based on Events and when Vuex came out, I did not predicted the problems that Events based approach would have when we are talking about large-scale application. Every action on the page requires about 10 to 15 events to keep all of the data in sync, it goes without saying that refactoring, maintaining, extending functionality or simply keep track of the current application state at this point become really painful. There is a good article that describe migration process from Events to Vuex, but it could be also used as a reference when you can and should use Events and when it is bad.

Unit Testing

Unit tests is an important part of any application, however unfortunately we have nothing here. To be fair to my colleagues, we have backend unit tests that cover crucial parts of the application, but frontend did not really had the ability to jump on that train. If you are starting a new project with Vue 2.x you have wide choice of tools to make testing happen. What I personally prefer to use is the same as vue-cli tool provides, Karma as a test runner, Mocha as a testing framework and Chai as an assertions library for Mocha. Without describing too much there is great article on scotch.io that explains how to tie that up all together. In the end you will have automated tests as a part of your build process and coverage report (including pretty HTML one).

E2E Testing

There is various ways how you can implement e2e testing. Recently I have made a setup using Nightwatch.JS framework. It’s extremely easy to setup and start writing your tests. Let me know if you want to get an example of the config.

Styling

It is important to make your styling consistent. You should figure out the approach you want to stick with and never go outside of it. Mobile-first, Desktop-first, choose one and always follow it.

Variables naming convention for colors/fonts should be abstract. Define the color scheme of your application and stick with something like $primary-font-color, $secondary-font-color, $helper-font-color, etc.

SCSS separated by component and example of global variable declarationSCSS separated by component and example of global variable declaration

Webpack

You will need to connect all of that processes. Compilation, Tests, ESLint, etc and there is a great tool for that called Webpack. It is basically a bundler that uses different loaders to process your code in different ways. There is a lot of different ways on how can you setup your config file and it really depends on project needs. What you should always keep in mind is that you should always have different configs for different environment. We are using “development” and “production” mode. Development mode enables Vue.JS devtools, shows our custom development panel, compiles JavaScript/SCSS with the sourcemaps, everything to make your debugging life little bit easier. Production mode creates a build that will be hosted on the live environment, minify, uglify, optimize assets, etc.

If you enjoyed this post, you may also like