Nuxt + Vuex - How do I break down a Vuex module into separate files?

In nuxt version 2.14^ you don't necessary have to create this in your store root index.js file.

import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';

const createStore = () => {
  return new Vuex.Store({
    namespaced: true,
    modules: {
      appLogic: appModule,
      api: apiModule
    }
  });
};

export default createStore

But instead, you can just leave your root index.js file as default or do what you need. No need to import.

store/index.js

export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

export const actions = {
   async nuxtServerInit({ state, commit }, { req }) {
   const cookies = this.$cookies.getAll() 
   ...
}

And this how it looks like, its very simple.

Folder structure

📦store
 ┣ 📂auth
 ┣ 📂utils
 ┣ 📂posts
 ┃ ┗ 📜actions.js
 ┃ ┗ 📜mutations.js
 ┃ ┗ 📜getters.js
 ┃ ┗ 📜index.js
 ┣ index.js

Example

store/posts/index.js you can just put the state function. You don't need to import the actions, getters and mutations.

export const state = () => ({ 
   comments: []
})

store/posts/actions.js

const actions = {
  async getPosts({ commit, state }, obj) {
    return new Promise((resolve, reject) => { 
       ...
    }
  }
}

export default actions

store/posts/mutations.js

 const mutations = {
    CLEAR_POST_IMAGE_CONTENT: (state) => {
       state.post_image_content = []
    }
 }
 
 export default mutations

store/posts/getters.js

const getters = {
    datatest: (state) => state.datatest,
    headlineFeatures: (state) => state.headlineFeatures,
}

export default getters

The effect is same as @CMarzin answer but much cleaner


I am using nuxt 2.1.0 If you want to have something like this :

Store module Vuex with Nuxt

In my store/index.js

Make sure you have namespaced: true

import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';

const createStore = () => {
  return new Vuex.Store({
    namespaced: true,
    modules: {
      appLogic: appModule,
      api: apiModule
    }
  });
};

export default createStore

In moduleOne

In my store/api-logic/index.js

import actions from './actions';
import getters from './getters';
import mutations from './mutations';

const defaultState = {
  hello: 'salut I am module api'
}

const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;

export default {
  state,
  actions,
  mutations,
  getters
}

In my store/api-logic/getters.js

export default {
  getHelloThere: state => state.hello
}

In module Two

In my store/app-logic/index.js

import actions from './actions';
import getters from './getters';
import mutations from './mutations';

const defaultState = {
  appLogicData: 'bonjours I am module Logic'
}

const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;

export default {
  state,
  actions,
  mutations,
  getters
}

In my store/app-logic/getters.js

export default {
  getAppLogicData: state => state.appLogicData
}

Anywhere in the app

 computed: {
  ...mapGetters({
   logicData: 'getAppLogicData',
   coucou: 'getHelloThere'
 })
},
mounted () {
  console.log('coucou', this.coucou) --> salut I am module api
  console.log('logicData', this.logicData) --> bonjours I am module Logic
}

Bonus Point

If you want to communicate between the modules for example a action in app-logic which trigger something in api-logic. So app-logic (module one) to api-logic (module two)

When you specify root: true it will start to look at the root of the store.

In store/app-logic/actions.js

  callPokemonFromAppLogic: ({ dispatch }, id) => {
    dispatch('callThePokemonFromApiLogic', id, {root:true});
  },

In store/api-logic/actions.js

  callThePokemonFromApiLogic: ({ commit }, id) => {

    console.log('I make the call here')
    axios.get('http://pokeapi.salestock.net/api/v2/pokemon/' + id).then(response => commit('update_pokemon', response.data))
  },

In store/api-logic/index.js add another entry

import actions from './actions';
import getters from './getters';
import mutations from './mutations';

const defaultState = {
  appLogicData: 'bonjours I am module Logic',
  pokemon: {}
}

const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;

export default {
  state,
  actions,
  mutations,
  getters
}

In store/api-logic/mutations.js add the pokemon mutation :p

  update_pokemon: (state, pokemon) => {
    state.pokemon = pokemon
  }

Anywhere in the app :

computed: {
  ...mapGetters({
    bidule: 'bidule',
    pokemon: 'getPokemon'
  })
},
mounted() {
  console.log('bidule', this.bidule)
  this.callPokemonFromAppLogic('1') --> the call 
  console.log('the pokemon', this.pokemon.name) --> 'bulbasaur'
},
methods: {
  ...mapActions({
    callPokemonFromAppLogic: 'callPokemonFromAppLogic'
  }),
}

At the end your Vue devTool should look like this :) Vue devTool screenshot store

And Voilà I hope It was clear. Code example :

https://github.com/CMarzin/nuxt-vuex-modules