Search code examples
vue.jsvuexvuex-modules

Vue.js Auto register Vuex modules in a specific way


I have just started with Vue.js and I am trying to use Vuex. I have the following structure inside my directory: src/store/

store
├── index.js
└── modules
    ├── app
    │   └── index.js
    └── auth
        └── index.js

Within each module, I have only one file called index.js, and within those files I define the getters, actions, mutations, etc of each module.

My question is the following: How can I auto register all these modules in the src/store/index.js file without having to register one by one. This will become a tedious task as my application grows. I also need that when each of these modules self-register, self-define the property namespaced: true

What I have tried so far:


import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const context = require.context('./modules', true, /index.js/); //only files with the name index.js

const modules = context.keys()
  .map(file => [file.replace(/(^.\/)|(\.js$)/g, ''), context(file)])
  .reduce((modules, [name, module]) => {
    if (module.namespaced === undefined) {
      module.namespaced = true;
    }

    return { ...modules, [name]: module };
  }, {});

const store = new Vuex.Store({
  modules: modules
});

export default store;

Thank you very much in advance.


Solution

  • From what I can gather, the issue resides in mapping the modules with context(file). For default exports I've gotten success with context(file).default, falling back on context(file) if that is undefined. I also don't see you stripping the '/index' part from your file's directory path.

    Using reduce makes the code more complicated than it needs to be, IMHO. You could just as easily do this with a forEach method:

    const context = require.context('./modules', true, /index.js/);
    const modules = {};
    
    context.keys().forEach((file) => {
    
      // create the module name from file
      const moduleName = file.replace(/(\.\/|\/index\.js$)/g, '');
    
      // register file context under module name
      modules[moduleName] = context(file).default || context(file);
    
      // override namespaced option
      modules[moduleName].namespaced = true;
    });
    
    const store = new Vuex.Store({
      modules, // ES6 shorthand for modules: modules
    })
    
    export default store;