DEV Community

mohamed benhida
mohamed benhida

Posted on

TIP - Import Vuejs Modules at once.

Hey in this Post We will see how can we add multiple Vuejs modules at once.

We all needed to import modules each time we create one on our modules folder like this (is from a real world project).

store/index.js

    import Vue from "vue";
    import Vuex from "vuex";

    import auth from "./modules/auth";
    import rows from "./modules/rows";
    import rooms from "./modules/rooms";
    import students from "./modules/students";

    Vue.use(Vuex);

    export default new Vuex.Store({
      modules: {
        auth,
        rows,
        rooms,
        students
      }
    });
Enter fullscreen mode Exit fullscreen mode

Vuejs

Like you see in the example above we have a 10 extra lines in our code. 5 lines to import the modules and 5 others to declare them on modules object.

Let's see now how can we reduce this 10 lines to 1 line So to do that we need to create an index.js file on modules folder that can listen to all the .js files inside modules folder and import them one by one.

modules/index.js

    import camelCase from "lodash/camelCase";
    const requireModule = require.context(".", false, /\.js$/); //extract js files inside modules folder
    const modules = {};

    requireModule.keys().forEach(fileName => {
      if (fileName === "./index.js") return; //reject the index.js file

      const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, "")); //

      modules[moduleName] = requireModule(fileName).default;
    });
    export default modules;
Enter fullscreen mode Exit fullscreen mode

modules/auth.js

    import auth from "../api/auth";

    const state = {
      isLoggedIn: !!localStorage.getItem("token"),
    };

    const getters = {
      isLoggedIn: state => {
        return state.isLoggedIn;
      }
    };

    const actions = {
      async loginUser({ commit }, data) {
        return await auth.login(data, data => {
          localStorage.setItem("token", data.access_token);
          commit("loginUser");
        });
      },
      async registerUser({ commit }, data) {
        await auth.register(data, data => {
          localStorage.setItem("token", data.access_token);
          commit("loginUser");
          return data;
        });
      },
      async logoutUser({ commit }) {
        return await auth.logout(data => {
          localStorage.removeItem("token");
          commit("logoutUser");
        });
      }
    };

    const mutations = {
      loginUser: state => {
        state.isLoggedIn = true;
      },
      logoutUser: state => {
        state.isLoggedIn = false;
      }
    };
    export default {
      state,
      actions,
      mutations,
      getters
    };
Enter fullscreen mode Exit fullscreen mode

Now we go back to our store/index.js and just import "./modules" equivalent to "./modules/index.js"

store/index.js

    import Vue from "vue";
    import Vuex from "vuex";

    import modules from "./modules";

    Vue.use(Vuex);

    export default new Vuex.Store({
      modules // Equivalent to => modules : modules(imported)
    });
Enter fullscreen mode Exit fullscreen mode

You can see now how our store/index.js is clean.

For more informations check chris vfritz repo.

Top comments (12)

Collapse
 
hkmsadek profile image
hkmsadek

This is good, but how you load store files from folders? Lets say you have

chats
index.js // module store file
users
index.js // module store file

How we can import these modules store files dynamically? I mean we may not know the folder (chats, users) names.

Collapse
 
heshamelmasry77 profile image
Hesham El Masry

any idea how this can be done please

Collapse
 
hkmsadek profile image
hkmsadek

I have done a nice set up for laravel vue module which you can see and also made a tutorial
github.com/hkmsadek/laravel-vue-mo...

youtube.com/watch?v=nW0eGVb0W-A&t=2s

Thread Thread
 
heshamelmasry77 profile image
Hesham El Masry

Thank you so much, you do a good trick really

Thread Thread
 
hkmsadek profile image
hkmsadek

Thanks :)

Collapse
 
hkmsadek profile image
hkmsadek

Hi everyone, anyone looking for an extended solution with the tutorial please look at this with gihub code
github.com/hkmsadek/laravel-vue-mo...

Watch the tutorial from here.

https://www.youtube.com/watch?v=nW0eGVb0W-A&t=2s

Thank you @mohamed for such a nice idea.

Collapse
 
morgothx profile image
Camilo Castro

Hi, thank you for the post.

I have a question if you can help me.

I have the following folder structure in my project

project
|
-store
|
|-constants.js
|-modules
|
|-someModule
|-otherModule
|-index.js (just as in your post)

This is a sample from my constants file

//Actions
export const USER_SET = 'user/SET'
export const USER_GET_ROLES = 'user/GET_ROLES'
//Mutations
export const USER_SET_BY_KEY = 'user/SET_BY_KEY'
export const USER_SET_ROLES = 'user/SET_ROLES'

And in my modules I use the constant as name for the actions, mutations, getters, like in this sample

const actions =
{
[constants.USER_SET]: ({commit}, user) =>
{
let response = {'data': user, 'key': 'user' }
commit(constants.USER_SET_BY_KEY, response)
},
}

The idea is that when I use in components, i use the constants file name too, this way I can change the name in one place

Like in this

...mapActions({
getRoles: constants.USER_GET_ROLES,

The thing is, even when the module are dinamically loaded by the index in the modules folder, Vuex doesn't recognize the actions, mutations, getters

I print the modules object in the index and i see that it has this properties empty

{
"customer": {
"state": {
"customers": null,
"contacts": null
},
"actions": {},
"mutations": {},
"getters": {}
},
.
.
.
.

}

If I go back to import every module manually and put then in the vuex individually, then vuex recognize the actions, mutations, getters

So thank you in advance if can you please point me in the right direction

p.s Sorry for my bad english, it's not my native language

Collapse
 
morgothx profile image
Camilo Castro

Nevermind, It was a problem with the way I was telling vuex to use modules but thank you anyway

Collapse
 
simo_benhida profile image
mohamed benhida

Glad you figured it out !

Collapse
 
isuke01 profile image
Łukasz Isu

Ohh that what I wanted, Thanks you soo much.

I created block builder, combined your solution + v-bind:is and it is great, I just create new file in modules and all other is done, I dont care for anything :D

Collapse
 
cedpoilly profile image
Cedric

Is it possible to lazy load the VueX modules?

Collapse
 
avatardemy profile image
Moyin Ademigoke

This is cool Mohammed, thank you.