Vue.js is great framework as it had very small learning curve, it’s easy to setup and it offers really nice transition from AngularJS. With it’s component approach you can split the application into small parts and reuse certain components around the application.
Problem comes when your application grows and you need to structure it better. This is the structure I’m using for my large scale Vue.js applications.
Setup Vue.js project
Best way to start with Vue.js is to use Vue CLI to setup your project.
Prerequisites: Node.js (>=6.x, 8.x preferred), npm version 3+ and Git.
1 |
$ npm install -g vue-cli |
or with yarn
1 |
$ yarn global add vue-cli |
and then initialize a project with webpack template (there are many more templates available)
1 |
$ vue init webpack large-scale-application |
This will ask us few question
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
? Project name large-scale-application ? Project description A Vue.js project ? Author Erol <erol@...> ? Vue build standalone ? Install vue-router? Yes ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Set up unit tests Yes ? Pick a test runner jest ? Setup e2e tests with Nightwatch? Yes ? Should we run `npm install` for you after the project has been created? (recom mended) yarn vue-cli · Generated "large-scale-application". # Installing project dependencies ... # ======================== yarn install v1.5.1 info No lockfile found. [1/5] Validating package.json... [2/5] Resolving packages... [3/5] Fetching packages... [4/5] Linking dependencies... [5/5] Building fresh packages... success Saved lockfile. Done in 43.98s. Running eslint --fix to comply with chosen preset rules... # ======================== yarn run v1.5.1 $ eslint --ext .js,.vue src test/unit test/e2e/specs --fix Done in 1.13s. # Project initialization finished! # ======================== To get started: cd large-scale-application npm run dev Documentation can be found at https://vuejs-templates.github.io/webpack |
and create a project. Great.
Initial structure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
├── build ├── config ├── node_modules ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ ├── main.js │ └── router │ └── index.js ├── static └── test |
Application structure is pretty basic and well structured. We mostly put all out code into src/components
, but it can quickly before clustered.
Improved structure for large scale applications
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
├── build ├── config ├── node_modules ├── src │ ├── assets │ │ └── logo.png │ ├── modules │ │ └── core │ │ │ ├── index.js │ │ └── projects │ │ │ ├── index.js │ │ │ ├── router.js │ │ │ ├── components │ │ │ │ └── ProjectStatus.vue │ │ │ ├── fields │ │ │ │ └── isCompleted.js │ │ │ └── pages │ │ │ │ ├── Project.vue │ │ │ │ └── Projects.vue │ │ │ ├── translations │ │ │ │ ├── de.js │ │ │ │ ├── en.js │ │ │ │ └── index.js │ │ └── users │ │ │ ├── index.js │ │ │ ├── router.js │ │ │ ├── components │ │ │ │ └── UserName.vue │ │ │ └── pages │ │ │ │ ├── UserProfile.vue │ │ │ │ └── Users.vue │ ├── App.vue │ ├── main.js │ └── i18n.js │ └── router.js ├── static └── test |
Structure follow the logic to split code into logical parts (projects, users, ..). I like to imagine that I’m able just to add or move the whole module folder and it should be plug-and-play.
Including modules
Each module has index.js
file which register everything important. For example, basic index.js
is
1 2 3 4 |
import './router' import './translations' import './filters/isCompleted' |
Then in main.js
we just import it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import Vue from 'vue' import App from './App' import router from './router' import './modules/projects' import './modules/users' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' }) |
Routes
For each module we can define custom routes by using vue-router addRoutes
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import router from '@/router' import Project from './pages/Project' import Projects from './pages/Projects' router.addRoutes([{ path: '/projects', name: 'projects.projects', component: Projects, props: false }, { path: '/projects/:id', name: 'projects.project', component: Project, props: true }]) |
Here we put page components into pages/
folder to have more organized structure.
Translations
There are many libraries for translation, currently I’m using vue-i18n and I’m quite satisfied. We create main 18n.js
to init translations.
1 2 3 4 5 6 7 8 9 |
import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) export default new VueI18n({ locale: 'en', messages: {} }) |
and then in each module translation file (for example modules/projects/translations/en.js
) we add translations.
1 2 3 4 5 6 |
import i18n from '@/i18n' i18n.mergeLocaleMessage('en', { 'PROJECTS': 'Projects', 'PROJECT': 'Project', }) |
or for other languages
1 2 3 4 5 6 |
import i18n from '@/i18n' i18n.mergeLocaleMessage('de', { 'PROJECTS': 'Projekte', 'PROJECT': 'Projekt', }) |
Core module
We also created a core module to hold code that doesn’t find anywhere else. This can be useful to store some global filters or components.
Other possibilities
This structure is excellent because it compacts the code together into logical components. Same logic is if we want to add state management (for example using Vuex), tests, assets or any other parts.