When it comes to project structure Vue has no documentation specifying a particular structure, it does provide a good starting layout (folder-by-type) generated with Vue CLI.
Folder by type is the most common architecture in Vue projects, it is simple and comes by default with every Vue app created using Vue CLI.
With this type of architecture you separate your files by types, for instance you store your components store routes utils etc. in their corresponding folders.
...
└── src
├── main.ts
├── App.vue
├── assets
│ └── logo.png
└── components
└── HelloWorld.vue
...
This is a pretty good architecture for small projects. However, as your app grows up you quickly notice that it becomes harder to navigate and develop, especially when you are focused on working on a specific feature.
Let's say you have a store management application with three features, which are the orders, products and clients. Working on a product's feature, you have to jump between several folders (assets, components, routes, stores, tests, etc.) and find the files that correspond to that feature.
When your project gets more and more features, this becomes really unmanageable, and you will end up with bloated component routes and store folders.
Pros:
- Most developers are familiar with this structure
- Ensures a flat folder structure
Cons:
- Each directory contains items that usually aren't relative to each other
- It can get quite tricky to find out which files are used by which features
Folder by feature or in other words, the modular architecture puts all of your files related to a specific feature into its own folder.
...
└── src
├── main.ts
├── App.vue
├── modules
├── products
│ ├── image.jpg
│ ├── ProductsModule.vue
│ ├── routes.ts
│ ├── index.ts
│ └── ...
├── order
│ └── ...
└── client
└── ...
...
You can notice that in this architecture, the root folders in the modules directory hold only feature related files.
Inside each module folder, you can have any structure that you want, as long as you expose the common module interface for registering it.
However, if you use folder-by-feature, you end up losing information about the type of file (because it's no longer in a components, store or assets folder).
Pros:
- The folder structure itself communicates the application features
- Separated files by feature
Cons:
- Sometime it is hard to draw the boundaries of the feature exactly
Which is the right one to pick ?
Unfortunately, there is no right or wrong here. Based on what I've seen, I can tell you that folder by feature performs better when it comes to scaling.
Hybrid structure:
Use both folder-by-feature and folder-by-type:
...
└── src
├── main.ts
├── App.vue
├── modules
├── core
│ ├── components
│ │ └── MyButton.vue
│ └── store
│ │ └── GlobalStore.ts
│ └── ...
├── products
│ ├── assets
│ ├── components
│ ├── pages
│ ├── store
│ ├── middlewares
│ ├── ProductsModule.vue
│ ├── routes.ts
│ ├── index.ts
│ └── ...
├── order
│ └── ...
└── client
└── ...
...
Now we have mixed features and types folders:
assets
,components
andmiddlewares
are the type onesproducts
,orders
andclients
are the features
Countless have been the hours of me trying to decide what structure to choose. I have tried both of them over the past years. I have come up to the conclusion that the Hybrid structure is the best one for me.
PS.
I was thinking about making a tutorial series about Vue's modular app architecture. Let me know in the comments what you thinki about it.
Bye ✋
Top comments (1)
Thanks for your article. However, I don't really agree with the architectures you propose. Of course, modular architecture allows you to separate by functionality, but you end up finding all types of files in them (you always get lost). And with hybrid architecture, you have to repeat all the file types by feature, which is a bit tedious when a new feature is added. The architecture I'm proposing (and adopting on all my projects) is effectively a mixed approach to separation by type and by functionality, but in this way :