Configuration

Each module needs several things to work properly.

index.js

In the project directory we create an entry file called index.js, needed to run the module.

It is required file.

  • index.js is created according to the Nuxt Modules rules,
  • The default exported function must be asynchronous,
  • We can add two additional functions:
    • beforeModule() - asynchronous function run before the module is loaded,
    • afterModule() - asynchronous function started after the module is loaded,
index.js
  export async function beforeModule() {
      // run before loading module
  }
  export default async function () {
    // module logic
  }
  export async function afterModule() {
      // run after loading module
  }
File is required and it is enough if it will have default functions without content.

config directory:

The greatest advantage of modules based on the VueMS library is their advanced expandability. Each module contains a directory config in which all configurations related to this module can be found.

The most important configuration file is index.js, which contains everything you need to load the module correctly. All other files are optional and depend on the purpose of the module. Some of the files kept in the config directory are just help files to keep order and structure in code.

Main configuration

The main configuration is placed in the config/index.js file. The file exports the properties needed to correctly configure the module.

It is required file.

Properties:


  • name
    • Type: String
    • Required: true

Module name including scope, used for correct module loading. The file path is built on its base.

For more information about naming the modules here.

  • order
    • Type: Number
    • Required: false
    • Default: 1000

The sequence of loading modules in the application. This may be important when the modules have a relationship with each other.

If the default value is not set to 1000, the modules will be loaded at the end.

The modules have a set decimal value (e.g. order: 20).

  • aliases
    • Type: Object
    • Required: true

The main mechanism of communication between the modules.

By specifying the alias, we create a name by which we will referencing the resources of this module.

config/index.js
  export default {
    ...
    aliases: {
        '@Core': '/',
        '@CoreComponents': '/components',
    },
  };
components/example.vue
  import List from '@Core/components/List/List';
  //or
  import List from '@CoreComponents/List/List';
We can create any number of aliases, referring to different places in the module.

  • relations
    • Type: Array
    • Required: false

If the modules are linked to each other, the names of the linked modules must be given here.

config/index.js
export default {
    ...
    relations: [
        '@ergonode/attributes',
        '@ergonode/media',
    ],
};
When the module is in this section and is not loaded, VueMS will return a reference error.

  • replacements
    • Type: Object
    • Required: false

It defines the elements of the module that will be replaced by others.
Simple mechanism of mapping elements to be replaced with a new element.

config/index.js
export default {
    ...
    replacements: {
      '@Core/components/coreComponent': '/components/myComponent',
    },
};
The item to be replaced can be any file and must exist in the application.

  • plugins
    • Type: Array
    • Required: false

It defines the plugins that are loaded globally into the application.

config/index.js
export default {
    ...
     plugins: [
        {
            ssr: true,
            src: './plugins/axios',
        },
     ],
};
The ssr flag is set when you want the plugin to be loaded at server startup.
  • ssr: false === mode: 'client'
  • ssr: true === mode: 'server'

  • css
    • Type: Array
    • Required: false

Defines css styles that are defined globally for the entire application.

export default {
    ...
    css: [
        './assets/scss/reset.scss',
        './assets/scss/font-inter-ui.scss',
    ],
};
More information here.

Example:

config/index.js
  export default {
      name: '@test/core',
      order: 10,
      aliases: {
          '@Core': '/',
      },
      relations: [
        '@test/messages',
      ],
      replacements: {
        '@Test/components/coreComponent': '/components/myComponent',
      },
      plugins: [
          { ssr: true, src: './plugins/axios' },
      ],
      css: [
          './assets/scss/reset.scss',
      ]
  };

Routing

File required if the module has pages and wants to define its own routing.
If the routing exists, you must create a file named routes.js and put all the routing rules in it.

Information from this file determines the routing passed to the @nuxtjs/router library,
which overwrites the default Nuxt routing.

The array exported in the file is parsed and combined by the VueMS and passed
to the main configuration of new Router().

@Core/config/routes.js
import {
    Icons,
    Pages,
    Tabs,
} from './imports';
import Privileges from './privileges';

export const ROUTE_NAME = {
    SETTINGS_UNITS: 'settings-units',
    SETTINGS_UNIT_EDIT: 'unit-id',
    SETTINGS_UNIT_EDIT_GENERAL: 'unit-id-general',
};

export default [
    {
        name: ROUTE_NAME.SETTINGS_UNIT_EDIT,
        path: '/settings/units/unit/:id',
        component: Pages.UnitEdit,
        redirect: {
            name: ROUTE_NAME.SETTINGS_UNIT_EDIT_GENERAL,
        },
        meta: {
            isMenu: false,
        },
        children: [
            {
                name: ROUTE_NAME.SETTINGS_UNIT_EDIT_GENERAL,
                path: 'general',
                component: Tabs.UnitGeneralTab,
                meta: {
                    title: 'Options',
                    breadcrumbs: [
                        {
                            title: 'System',
                            icon: Icons.Settings,
                        },
                        {
                            title: 'Units',
                            routeName: ROUTE_NAME.SETTINGS_UNITS,
                        },
                    ],
                    privileges: [],
                },
            },
        ],
    },
];
Here are described privileges.js and imports.js files.

Extend

Creating new modules is not all we usually need. Sometimes you need to replace certain elements or add some to already existing solutions.

In order not to modify existing modules, VueMS library provides a solution to easily extend already existing mechanisms. Thanks to it we have a lot of possibilities to extend modules from other modules.

In order to add any extensions you need to create an extends.js file and use specific properties in it depending on what you want to achieve.

You don't need to create an extends.js file if you don't want to extend anything

Properties:


  • replaceRoutes
    • Type: Array

This functionality allows you to replace a routing page by his name. The mechanism is based on routing and extends existing routing.

replaceRoutes:
- name - existing router name what we want replace,
- routes - new routing to replace,

@Products/config/extends.js
export default {
    replaceRoutes: [
        {
            name: 'products',
            routes: {
                name: 'products-new',
                path: '/new-products',
                component: Tabs.Product,
                meta: {
                    title: 'New Products',
                    visible: false,
                    breadcrumbs: [
                        {
                            title: 'New Products',
                            icon: Icons.Product,
                        },
                    ],
                    privileges: [],
                },
            },
        },
    ],
};
The extended routing must exist. The mechanism substitutes all routing with the given name.
First the routing is replaced and then extended (extendRoutesChildren), so if a routing is added to the given name, it will be added correctly.

  • extendRoutesChildren
    • Type: Array

This functionality allows you to add a new children to a routing page. The mechanism is based on routing and extends existing routing.

extendRoutesChildren:
- name - existing router name what we want extend,
- children - array with router to extend,

@Products/config/extends.js
export default {
    extendRoutesChildren: [
        {
            name: 'product-id',
            children: [
                {
                    name: 'product-id-variants',
                    path: 'variants',
                    component: Tabs.ProductVariantsTab,
                    meta: {
                        title: 'Variants',
                        visible: false,
                        breadcrumbs: [
                            {
                                title: 'Products',
                                icon: Icons.Product,
                            },
                            {
                                title: 'Catalog',
                                routeName: 'catalog-products',
                            },
                        ],
                        privileges: [],
                    },
                },
            ],
        },
    ],
};
The extended routing must exist, if it does not have the children property then it will be added.

  • extendStore
    • Type: Object

A mechanism to expand existing Vuex store. If there is a need to extend an already existing Vuex store then you should use this property.

When using extendStore, the key is the name of the existing Vuex store and the value is the file that exports the content of the extended methods.

Vuex store runs on vuex modules mechanism.

@Products/config/extends.js
export default {
    extendStore: {
        product: () => import('@Products/extends/store/product').then(m => m.default || m),
    },
};
If you want to expand the Vuex store, you should place it in a different directory than the store. We recommend that you use the extends directory.

Extend vuex store

If you create the store directory on the module root and place a Vuex store with an existing name in it, it will be replaced (The order of loading the modules is important).

  • extendComponents
    • Type: Object

One of the important mechanisms is the possibility of extending existing components from outside. The operation of the components allows them to be reusable and used anywhere, but the problem is when we want to extend an existing component in a specific business context. Therefore, we have prepared a mechanism that allows you to easily inject a component into a specific location.

The component expansion mechanism works similarly to the placeholder placed in the text, the placeholder is replaced by the data passed on to it. Our component expansion mechanism works the same way, with the appropriate placeholders scattered throughout the application, which can be referenced and passed on to the component.

There are predefined places ready for expansion throughout the application.

Example:

config/extends.js
  const Navigation: () => import('@Notifications/components/Navigation');

  export default {
    extendComponents: {
      NAVIGATION_BAR: [
        {
          component: Navigation,
          props: {
            propsToSend: true,
          },
        },
      ],
    },
  };
components/Extends.vue
  <template v-for="(component, index) in extendedComponents">
      <Component
          :is="component.component"
          :key="index"
          v-bind="component.props" />
  </template>

  <script>
    export default {
      computed: {
        extendedComponents() {
          return this.$getExtendSlot('NAVIGATION_BAR');
        },
      },
    };
  </script>
Placeholder names are defined by the access path to the component
(e.g @Products/components/Forms/ProductForm - extend product form component). We recommend this approach because it is very clear.
There is a global $getExtendSlot method in the application that takes all the components passed for expansion and places them in a prepared place.

  • extendMethods
    • Type: Object

The mechanism works the same as extendComponents, but instead of the components the placeholders are filled with methods.

The methods can return information or just set up some data.

The methods can take any parameters, it depends on the information provided while creating the placeholder.

Example:

@ExtendStore/config/extends.js
  export default {
      extendMethods: {
          '@Test/store/test/action': ({
              $this, data = [],
          }) => {
              console.log({$this, data});
              return data;
          }
      },
  }
@Test/store/test/action
  export default {
      create({ state }) {
          ...
          this.$getExtendMethod('@Test/store/test/action');
          ...
      }
  }
There is a global $getExtendMethod method in the application that takes all the methods passed for expansion and places them in a prepared place.
The methods work in asynchronous mode.

Helpers

Support files are files that are not imposed by VueMS, they are to make your work easier.

  • privileges.js

A file storing all permissions imposed by the module. Used mainly in routing - routes.js.

export default {
    SETTINGS: {
        namespace: 'SETTINGS',
        create: 'SETTINGS_CREATE',
        read: 'SETTINGS_READ',
        update: 'SETTINGS_UPDATE',
        delete: 'SETTINGS_DELETE',
    },
};
  • imports.js

A file storing all imports needed in the configuration files.

export const Pages = {
    Login: () => import('@Core/pages/login/index').then(m => m.default || m),
};

export const Tabs = {
    MainSettingsTab: () => import('@Core/components/Tabs/MainSettingsTab').then(m => m.default || m),
};
Of course, if you want, you can create your own support files. The config directory is used for this.