How To Structure a Massive Vuex Store for a Production App
Domagoj Vidovic
Posted on July 12, 2021
When looking at Vuex tutorials, you can see most of them are quite simple.
The logic is explained well, but scalability suffers. How will this work in my production app?
Here’s a simple store example from Vuex official docs:
There’s no need to explain this. I assume that you already have some Vue and Vuex knowledge prior to this article.
My goal is not to explain what a store, state, or mutations are.
Instead, I want to show you a massive store with 1,000+ state attributes, mutations, actions, and getters.
I want to teach you how to structure the store for the best maintainability, readability, and reusability.
It can have 100,000+ attributes. It would still be clear.
Let’s dive in.
Meet Modules
As we already said, keeping everything in one file will create a mess. You don’t want a 50,000+ LOC file. It’s the same as keeping your app in one component.
Vuex helps us here by dividing the store into modules.
For the purpose of this example, I will create a store with two modules. Note that the process is the same for 100+ modules, as well as 100+ actions, getters, and mutations within every module.
The namespaced
attribute is incredibly important here. Without it, actions, mutations, and getters would still be registered at the global namespace.
With the namespaced
attribute set to true, we divide actions, mutations, and getters into the modules as well.
This is really helpful if you have two actions with the same name. Having them in a global namespace would create clashes.
As you can see, the module is completely “local” right now. We can access it only through the user object on the state.
Exactly what we want for our massive application.
Cool, now we have a store divided into modules!
However, I don’t like the hardcoded strings for actions. It’s definitely not maintainable. Let’s address this issue.
Types To Save You From Headaches
We don’t just want to access every property from every module in every file. That sentence sounds like hell.
We want to import them first. Then use mapGetters
, mapActions
, or mapMutations
to achieve that.
This gives you a clear view of store attributes used by your Vue file.
But that’s not enough. Everything is still in one file. Let’s see what we can do to scale it properly.
Folder Structure
Ideally, we want to split modules into different folders. Within those modules, we want to split their mutations, actions, getters, state attributes, and types across different files.
Folder store
will be created in the root folder of our project.
It will contain two things:
-
index.js
file -
modules
folder
Before explaining the index.js
file, let’s see how we divide a single module. Let’s check the user
module.
All of its actions, mutations, and getters should be listed in the types.js
file. So, something like:
We’ll have a clear view by importing those consts every time we want to use them.
Let’s look at the actions now. We want to move them to the actions.js
file.
To do so, we only need to copy the actions
object within the module and export default
it, while importing the types:
We will do the same thing for mutations and getters. The state attributes will remain in index.js
(within the user module folder):
Now we have all of our modules divided into multiple files.
The one thing remaining is to link all those modules in the index.js
file within the store
folder:
Conclusion
By using this architecture, we had zero problems with scalability in our massive production app.
Everything is so easy to find.
We know exactly where all the actions are triggered.
The system is highly maintainable.
If you have any recommendations for the improvements, please let me know. I would love to hear your opinion.
Posted on July 12, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.