Vuex Modules Tutorial, how to scale your Store

Vuex modules are an efficient way to make your Vuex store scalable.

Share This Post

We already know Vuex from this tutorial. In fact, with it, you can manage all your data (the state) from a single place: the store. While this sounds good, it comes with a drawback: your store can become messy. After all, the store is the file that contains all the data your application is working on. This is not really what we want in order to have maintainable code. As we will see in this Vuex Modules Tutorial, modules are an elegant way to solve this problem by dividing your store into different files.

Vuex Modules Tutorial

Introducing Modules

Vuex Modules are simply Vuex stores inside other Vuex stores. Don’t worry, it is much simpler than it sounds. In our previous tutorial, we created a store with mutations, getters, and actions. Well, you can also create a store by including one or more modules in it. Before we do that, we will see in this Vuex modules tutorial on how to create a module.

Since a Vuex store can have multiple module, we recommend creating a folder named /store in your project. In it, create index.js to write the store itself, and one js file for each store module you need. In our example, we will have only one module, but you can have more than one.

In this Vuex Modules Tutorial we need to define a structure for our store folder.

A module is just a store, and you write it exactly like a store, except you don’t use Vuex.Store. Instead, you define it as a normal object. Take a look at the example below, a simple authentication store. You can save the code below in /store/auth.js.

import axios from 'axios'

const auth = {
  state: {
    userdata: null
  },
  mutations: {
    login (state, payload) {
    state.userdata = payload
  },
  logout (state) {
    state.userdata = null
  }
  },
  actions: {
    authenticate ({ commit }, { username, password }) {
    axios({
      method: 'post',
    url: '/my/backend/url',
    data: {
      username: username,
      password: password
    }
    })
      .then(response => {
      if (response.status === 200) {
        commit('login', response.data)
      }
  }
  },
  getters: {
    loggedIn. function (state) {
    return state.userdata !== null
  }
  }
}

export default auth

Including modules in the Store

Now the next part of our Vuex Modules tutorial: including a module in the store. Including a module is as simple as defining the modules attribute. Your Vuex Store will look something like this:

import Vue from 'vue'
import Vuex from 'vuex'
import auth from './auth'
Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    auth,
    // other modules here ...
  }
})

And this is it! Now, we only need to know how to call actions, mutations, and getters of our module from our application.

By default, modules are not namespaced. This means that all the properties of the module will be reflected directly in the store. This means that our store will have the mutation login, even if we defined it in the auth module. We can access it from any Vue component like below.

// State
this.$store.state.userdata
// Mutation
this.$store.commit('login', { username: 'logged_user' })
// Action
this.$store.dispatch('authenticate', { username: this.username, password: this.password })
// Getter
this.$store.getters.loggedIn

Of course, using modules in this way reduces the complexity when writing the store, but not when using it.

Namespacing Vuex Modules

The next frontier of our Vuex Modules Tutorial is namespacing our modules. Namespacing a module simply means it won’t inject its properties in the store directly. Instead, to access them, we need to reference it in a tree-like structure. This approach requires a little bit more code but is way more scalable and maintainable. To define that your module will be namespaced, simply set the namespace property to true.

import axios from 'axios'

const auth = {
  namespaced: true,
  // State, mutations, actions, getters ...
}

export default auth

You don’t even need to change the code in your store index. That’s all you need to do on the module side. Instead, you need to do something when referencing the module properties. In fact, they are not on the root of the store anymore. To reference them, you need to call them with a path-like naming convention. This naming convention uses the module name and the property name, separated by a slash.

// State
this.$store.state.auth.userdata
// Mutation
this.$store.commit('auth/login', { username: 'logged_user' })
// Action
this.$store.dispatch('auth/authenticate', { username: this.username, password: this.password })
// Getter
this.$store.getters['auth/loggedIn']

You can also nest multiple modules with the same naming convention: module/nestedModule/login. Furthermore, you can mix namespaced modules with non-namespaced modules. Imagine that nestedModule is not namespaced but module is, the login property in nestedModule will be accessed with module/login.

Renaming modules

You can also rename modules when you include them in the modules section. Instead of listing them as we did before, provide a key:

import Vue from 'vue'
import Vuex from 'vuex'
import auth from './auth'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    authentication: auth,
    // other modules here ... 
  }
})

In this case, we will reference our module with authentication, not with auth. That’s because authentication is its name inside this store.

In Conclusion

In this Vuex Modules Tutorial, we saw how to make your store modular. Each module is basically a store, with all its properties: mutations, actions, getters, and so on. Once you have a module, you can import them in a store or in another module by referencing it inside the modules property. Furthermore, namespacing modules allow you to access the properties in a tree-like structure and avoid conflicts. In case you want to dive deeper into Vuex Modules, you can always take a look at the official docs.

What do you think of Vuex modules? Do you use them to better structure your application? Let me know your opinions in the comments!

Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.
Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.

Alessandro Maggio

2019-05-16T16:30:44+00:00

Unspecified

Dev

Unspecified