Building Larger Apps
Vue.js is designed to be as flexible as possible - it’s just an interface library that doesn’t enforce any architectural decisions. While this can be very useful for rapid prototyping, it could be a challenge for those with less experience to build larger scale applications with it. The following is an opinionated perspective on how to organize larger projects when using Vue.js.
Modularization
Although the standalone build of Vue.js can be used as a global, it is often better to utilize a modularized build system to better organize your code. The recommended approach of doing so is by writing your source code in CommonJS modules (the format used by Node.js, and also the format used by Vue.js source code) and bundle them using Browserify or Webpack.
Here are some build setup examples on GitHub:
Single File Components
In a typical Vue.js project we will be breaking up our code into many small components, and it would be nice to have each component encapsulate its CSS styles, template and JavaScript definition in the same place. A bonus for using the previously mentioned build tools is that they both provided mechanisms to transform the source code before bundling them together, and with a bit of pre-processing we can write our components like this:
If you are into pre-processors, you can even do this:
This is achieved via using the Vueify transform for Browserify, or with Vue-loader for Webpack.
Routing
You can implement some rudimentary routing logic by manually listening on hashchange and utilizing a dynamic v-component
.
Example:
1 | <div id="app"> |
1 | Vue.component('home', { /* ... */ }) |
With this mechanism it’s very easy to leverage standalone routing libraries such as Page.js or Director.
Communication with Server
All Vue instances can have their raw $data
directly serialized with JSON.stringify()
with no additional effort. You can use any Ajax component you like, for example SuperAgent. It also plays nicely with no-backend services such as Firebase.
Unit Testing
Anything compatible with a CommonJS-based build system works. A recommendation is using the Karma test runner together with its CommonJS pre-processor to test your code modularly.
The best practice is to export raw options / functions inside modules. Consider this example:
1 | // my-component.js |
You can use that file in your entry module like this:
1 | // main.js |
And you can test that module like this:
1 | // Some Jasmine 2.0 tests |
Since Vue.js directives react to data updates asynchronously, when you are asserting DOM state after changing the data, you will have to do so in a Vue.nextTick
callback. Alternatively you can set Vue.config.async = false
during tests, so you can assert the DOM state synchronously right after the data change.
An Example
The Vue.js Hackernews Clone is an example application that uses Webpack + vue-loader for code organization, Director.js for routing, and HackerNews’ official Firebase API as the backend. It’s by no means a big application, but it demonstrates the combined usage of the concepts discussed on this page.