Best way to organize files in Vue
Vue.js is, in my opinion, the most beautiful JS framework currently available. One of the features I like the most is the .vue single-file components. But it can get challenging to manage larger ones, especially when you start creating custom sub-components and adding static assets.
I have been doing projects with Vue JS for over two years now. And along the way, I've come across many learnings. This tutorial is the outcome of experience working on a range of projects, and witnessing scalability and maintainability issues.
I'm talking about projects with many Vuex stores, hundreds of components, and many pages. It was a rewarding experience for me, as I discovered many interesting patterns to make the project scalable. I also had to fix some bad habits that resulted from earlier small projects.
As a result of this, I would like to share my best practices for you if you're in the moment of building a Vue JS application. These practices or tips are about what you should do, use and avoid, and generally just some plain old good advice.
These tips help you develop a more efficient project that's easier to maintain and share for small, mid-range, and large projects.
Do you prefer to watch a video about this topic?
Even if you have heard this many times, naming conventions are fundamental. You can use this for every programming and markup language and, of course, for component file names. The naming convention's primary purpose is to give names meaning so that they are as informative as possible for the developer.
Some conventions have also been established for Vue.js. And this is essential even for small projects.
For example, component names should always be multi-word. Use
ProfileCard instead of
// Bad - Card.vue - Modal.vue - Button.vue - Notification.vue // Good - UserCard.vue - ProfileCard.vue - UserModal.vue - UserButton.vue - UserNotification.vue
Furthermore, child components tightly coupled with their parent should include the parent component name as a prefix. For example,
// Bad - UserCard.vue - Image.vue - Icons.vue - Button.vue // Good - UserCard.vue - UserCardImage.vue - UserCardIcons.vue - UserCardButton.vue
If you have components that are used only once per page, you should start with the prefix
The to indicate that it can only be one component. For example,
// Bad - Navbar.vue - Footer.vue - Header.vue - Menu.vue // Good - TheNavbar.vue - TheFooter.vue - TheHeader.vue - TheMenu.vue
It's easier to read and understand if component names start with the highest-level meaningful words and end with descriptive modifying words.
Please avoid this crazy unreadable chaos of words
// Bad - ClearSearchButton.vue - ExcludeSearchInput.vue - StartupCheckbox.vue - RunSearchButton.vue - SearchInput.vue - TermsCheckbox.vue
Instead, use a more logical order.
// Good - SearchButtonClear.vue - SearchButtonRun.vue - SearchInput.vue - SearchInputQuery.vue - SettingsCheckbox.vue - SettingsTerms.vue
Always use the full name instead of abbreviation in the name of your components. For example, don’t use
SettingsUN, use instead
// Bad - SettingsUN.vue // Good - SettingsUserNotification.vue
That's important to avoid misunderstandings. Make sure that everything is organized, uniform, and understandable. But that's just the basics and works fine for small projects.
I have seen this all too often, and with mid-range and larger projects, this becomes a nightmare. All components are in the components folder. All assets are in the central assets folder, and child components are only indicated by prefacing the name of its parent, which looks super fun over two layers and more, like:
// Bad src assets - user-card-button-apply-bg.png - user-card-header-logo.png components - UserCard.vue - UserCardButtonApply.vue - UserCardFooter.vue - UserCardHeader.vue - UserCardSettingsNotificationStatus.vue
And that becomes confusing over time. How can we fix it?
We are putting the child components and assets in separate folders. With this new structure here looks everything much cleaner and organized. You have here all the related asset files related to the parent and child components. Furthermore, you can use shorter filenames for all files.
// Good src assets components UserCard assets - button-apply-bg.png - header-logo.png components Settings - NotificationStatus.vue - ButtonApply.vue - Footer.vue - Header.vue - UserCard.vue
You immediately recognize what belongs together and thus save a lot of time. That's much better for mid-sized projects.
- It's easy to understand for other devs.
- It works in every build system.
- It looks much cleaner and organized.
But if the project grows over time or you are working on a large project, you will quickly reach the limits with this structure, and it will still be confusing at a certain point, especially when the number of components and other files gets very high.
Imagine you have hundreds of files in the components folder. The source code navigation is not simply inside the components folder and knowing the purpose of each one. And the same for any other file type.
Also, debugging can be very time-consuming. You need to jump from file to file and draw a mental map of how a simple process works to determine the root cause of a bug.
That sounds not really enjoyable, right?
A better pattern is to structure your project using modules and consider each module as a small project while reducing the disadvantages just described, so you get a structure like this.
src Authentication components Notification - Card.vue - Button.vue - Status.vue - Notification.vue Dashboard Login
You will end up in a modular application with fewer files per module. And each file in a module should only contribute to the module's responsibility. In case a module still has too many files, you should split them into smaller modules.
This structure simplifies the navigation in the source code, debugging, and general maintainability enormously.
But there is something important to note here. You have to isolate your modules as much as possible.
Having a modular system usually implies having interaction between the different components in the application, and that's why isolating the modules as much as possible is so important.
Furthermore, I also recommend to outsourcing many used code in separate files, for example, in little service and helper pieces.
//src //Authentication //components helper services //Dashboard //Login
And of course, it makes sense that each module, if required, has its own Vuex store, router configuration, or files for all communication channels with other resources, like API calls to the backend or other modules.
//src //Authentication api store router //components //helper //services //Dashboard //Login
These principles allow teams to collaborate on large projects independently, with the confidence of not breaking other components in the application.
I recommend thinking about new projects with this structure and migrating existing projects as soon as possible. It may be a lot of work at first, but you will see the benefits.
How would you structure your project? Let's discuss this topic in the 👉 comments