Architect state management in a large scale Vue.js application

Arun Redhu
Vue.js Developers
4 min readMay 19, 2019

--

Now a days, web application are more complex & dynamic and has to deal with a large amount of data along with intuitive and interactive user experience. So, state management has become one of the important decision that has to make by the developer at the time of architecting the application.

This article is 3rd part of the series Architect a large scale Vue.js Application . You can find the supporting boilerplate here. In this, I am going to explain, how should we architect the state of our application.

Vue.js provides its own official state management pattern + library named as Vuex and it is one of the most recommended library that should be used for state management in Vue.js applications. Here, I will not go deep into the Vuex core concepts such as what is vuex, mutations, or actions etc. I will write another separate article explaining them in detail.

When we talk about the state in a component based application, then it is generally of 2 types:

  • Component local state, limited to just in the scope of component,
  • Application level state, shared across the application components

Some people suggests, we should keep all the state (local + global) on the application store and while other suggests local states of component should be managed by the component itself rather than keeping all the state (local + global) on application store. I feels that, 2nd approach is the good way to manage the state, it keeps the application store more cleaner and manageable.

Now, the question is, application could be very large & complex and needs to manage huge amount of data flow, then in this case how should we organise the application state? The simple answer is, in a modular way. You remember, in the first article, we organised the application into multiple feature modules. In the same way, we will organise the application state on feature level and each feature module will be responsible for managing the related states.

In the project structure, each feature module has a shared/state folder. This is where, we will keep all the state files related to that feature module. For eg. user feature module will have its state files in users/shared/state and suppose it will have states such as user list data, user details, etc. then we will create one file for each state, let’s say, for user list data we created users-data.js under users/shared/state and each file looks like below:

There are few things, I would like to explain about the above code snippets:

  • I did put all the mutations, actions & related constants in a single file as these are linked to each other. Also, we can have them in separate files but I thought, it would be good to have these in a single file.
  • reflectKeys is just a method which mirrors the keys i.e. it returns an object with supplied string as key and value. Also, we can add a prefix to key values as well. It is just used for managing the constants string for mutation types and action types rather than hardcoding the strings.
  • Vuex provides its own way to namespace the state, mutations, actions, etc. but I am using other way to namespace by using prefix. I found it as more comfortable and convenient because we don’t need to add namespace part everywhere for calling actions, mutations or state getters etc. But as per your interest, you can use vuex namespace.
  • In Vuex, we can commit the mutations directly without having actions. We need actions in the async operations. I suggest, use actions instead of committing the mutations directly, for both sync and async operations. You can see, I just exported action types not mutation types. This is because, it will maintain the consistency, only actions will be responsible for triggering the state updates.
  • As you can see, actions are just committing the mutations, all the business logic, for eg. API calling as been moved to services. In the same way, we need to maintain the actions more clean and having the business logic into services. This makes the application more flexible by having a clear separation into the business logic and state management.

Each feature module has a state file at the root of that module. This file is responsible for combining all the states of that feature module. For eg. in our case, it issrc/app/users/user-state.js. We are using Vuex modules to combine all the states of this feature module and looks like below:

Feature level state combining using Vuex modules

In the same way, all feature modules state will be combined into the application state using the same concepts i.e. Vuex modules. For eg. src/app/app-state.js will look like below:

You can see that, I am importing the usersState from users feature module.

There will also be cases in which we need to share states across different feature modules. These type of state can be defined into the app/shared/state and then needs to be integrated into application state as well.

I prepared the boilerplate around this architecture. You can find it here https://github.com/arunredhu/vuejs_boilerplate. I look forward to see your contribution.

Conclusion:

State management in a large scale application is very challenging and needs to have a well defined architecture. The architecture explained in this article is general and working for me in many large applications but it could vary based on the type of the application and developer needs.

--

--

Arun Redhu
Vue.js Developers

I am a full stack JavaScript developer by profession and tech enthusiast at heart. More about me https://arunredhu.in/