{"id":14964331,"url":"https://github.com/ergonode/vuems","last_synced_at":"2025-04-07T12:09:05.806Z","repository":{"id":38688115,"uuid":"246783270","full_name":"ergonode/vuems","owner":"ergonode","description":"A simple mechanism to transform a monolithic Vue application into an application based on Micro Services architecture","archived":false,"fork":false,"pushed_at":"2023-06-21T23:24:02.000Z","size":27319,"stargazers_count":78,"open_issues_count":15,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-31T10:11:09.490Z","etag":null,"topics":["javascript","micro-services-architecture","microfrontends","nuxtjs","vuejs"],"latest_commit_sha":null,"homepage":"https://vuems.ergonode.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"osl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ergonode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-03-12T08:37:53.000Z","updated_at":"2024-08-29T08:13:32.000Z","dependencies_parsed_at":"2023-09-24T18:10:19.674Z","dependency_job_id":null,"html_url":"https://github.com/ergonode/vuems","commit_stats":{"total_commits":52,"total_committers":3,"mean_commits":"17.333333333333332","dds":0.09615384615384615,"last_synced_commit":"2948a1da7b933c6a3adbabf73575b4e5d0e89d79"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergonode%2Fvuems","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergonode%2Fvuems/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergonode%2Fvuems/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergonode%2Fvuems/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ergonode","download_url":"https://codeload.github.com/ergonode/vuems/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247648978,"owners_count":20972945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","micro-services-architecture","microfrontends","nuxtjs","vuejs"],"created_at":"2024-09-24T13:32:59.844Z","updated_at":"2025-04-07T12:09:05.783Z","avatar_url":"https://github.com/ergonode.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@ergonode/vuems\" rel=\"noopener noreferrer\"\u003e\n    \u003cimg width=\"300\" src=\"docs/static/logo.svg\" alt=\"VueMS logo\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003ch1 align=\"center\"\u003eVue Micro Services\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@ergonode/vuems\"\u003e\n    \u003cimg alt=\"NPM\" src=\"https://img.shields.io/npm/v/@ergonode/vuems\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@ergonode/vuems\"\u003e\n    \u003cimg alt=\"NPM\" src=\"https://img.shields.io/npm/l/@ergonode/vuems\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003ch4 align=\"center\"\u003e\u003ca href=\"https://vuems.ergonode.com/\"\u003e📖 Read the documentation\u003c/a\u003e\u003c/h4\u003e\n\u003cbr\u003e\n\n\u003e A simple mechanism to transform a monolithic Vue application into an application based on Micro Services architecture.\n\n## Inspiration\n\nCombination of `Vue` and `NuxtJS` frameworks gives us the opportunity to build any web application we want.\nUnfortunately, application built on this approach is monolithic and we cannot extend its behavior. Of course we can extend project with some elements, but these are small fragments that do not add much. In addition, `NuxtJS` forces developers to have a specific directory structure (page, middleware, store, etc.). This gives us a rigid application built on specific principles.\n\n\n`VueMS` gives the possibility to divide the application into micro parts that use all `Vue` + `NuxtJS` mechanisms, but do not have their limitations. Structure of these parts is identical to the monolithic application, however each module can operate separately, communicate and interact with one another. Modules can be both small elements (single component, plugin) and complex structures (components, plugins, middleware, store, pages).\n\nAdvantages of VueMS:\n\n- Each module can have its own business context communicating separately with the backend application.\n- Modules can be turned active or inactivate anytime which allows to customize the application for each client individually.\n- Modules can be loaded locally within the application and downloaded from external servers ([npm][npm], [Verdaccio][verdaccio]).\n- Thanks to having modules on external servers, we can version them, therefore the modules are independent and easy to expand.\n- The customer can upgrade any package or replace it with another one.\n\n---\n## Detailed Start\n### 📦 Requirements\n\n- [Vue.js][vue] (v2.x)\n- [Nuxt.js][nuxt] (v2.x)\n- [Nuxt Router][router]\n\n\n### 🚀  Power Supplies\n- [Vuex][vuex] - optionally\n- [i18n][i18n] - optionally\n\n---\n## Setup\n\n#### 1. Add `@ergonode/vuems` dependency to your project.\n\n```bash\nnpm install @ergonode/vuems\n# or\nyarn add @ergonode/vuems\n```\n\n#### 2. Add `@ergonode/vuems` to the `buildModules` section in the `nuxt.config.js` file.\n\n```js\n  export default {\n    ...\n    buildModules: [\n      ['@ergonode/vuems', { /* module options */ }]\n    ],\n    ...\n  }\n```\n\n  ##### Using top level options\n\n  ```js\n  export default {\n    ...\n    buildModules: [\n      '@ergonode/vuems'\n    ],\n    vuems: {\n      /* module options */\n    },\n    ...\n  }\n  ```\n---\n## Options\n\n### `modules`\n\n- Type: `Object`\n- Default: `{ npm:[], local: [] }`\n\nObject with all loaded modules.\n\n### `required`\n\n- Type: `Array`\n- Default: `[]`\n\nArray with required module names.\n\n### `modulesDir`\n\n- Type: `String`\n- Default: `modules`\n\nLocal modules directory name.\n\n### `vendorDir`\n\n- Type: `String`\n- Default: `vendor`\n\nNpm modules directory name. Directory is temporary and used by symbolic link.\n\n### `nodeModulesDir`\n\n- Type: `String`\n- Default: `node_modules`\n\nDirectory where installed npm modules are to be found.\n\n### `vuex`\n\n- Type: `Boolean`\n- Default: `true`\n\nIf Vuex library is used.\n\n### `i18n`\n\n- Type: `Boolean`\n- Default: `false`\n\nIf i18n plugin is used.\n\n### `isDev`\n\n- Type: `Boolean`\n- Default: `false`\n\nIs development mode on.\n\n### `logLoadedModules`\n\n- Type: `Boolean`\n- Default: `false`\n\nLog all loaded modules.\n\n### `verbose`\n\n- Type: `Boolean`\n- Default: `true`\n\nLog module process.\n\n### `directories`\n\n- Type: `Object`\n- Default:\n```\n{\n    assets: 'assets',\n    components: 'components',\n    config: 'config',\n    layouts: 'layouts',\n    middleware: 'middleware',\n    pages: 'pages',\n    plugins: 'plugins',\n    store: 'store',\n}\n```\n\nDirectory structure for module.\n\n### Options example\n```js\nvuems: {\n    required: [\n        '@my/core',\n    ],\n    modules: {\n        local: [\n          '@my/core',\n          '@my/authentication',\n        ],\n        npm: [\n            '@test/users',\n            '@test2/import'\n        ]\n    },\n    isDev: process.env.NODE_ENV !== 'production',\n}\n```\n---\n## Module creating\n\n### Introduction\nModules are based on mechanisms [Nuxt Modules](https://nuxtjs.org/guide/modules/), but they have no restrictions on the structure. The module can have any structure, which means it can be a single functionality or a large and complex business logic. We divide modules at our discretion and it is also our decision what structure they will have.\n\n### Types\nModules can be divided into two types. The type determines the place from which the module is loaded.\n- **local**: Modules placed locally in the project in the default `modules` directory. These modules are only available in the project and are fully modifiable.\n:warning: Changing the default directory for local modules (`modulesDir` option)\n- **npm**: Modules hosted on external servers (npm). Module is available when we  install the package in the project (`npm i module-name`). These modules are unmodifiable and they are updated only by upgrading the npm package version.\n:warning: Changing the directory for installed npm packages (`nodeModulesDir` option).\n:warning: Changing the directory attached to the symbolic link (`vendorDir` option).\n\n### Naming modules\n#### Local\nThe names of local modules are determined based on the directory structure. The adopted and recommended directory structure is based on the concept [npm scope](https://docs.npmjs.com/about-scopes).\n```\nmodules/\n|-- @test/\n    |-- my-local-module/\n|-- users/\n```\n#### Npm\nThe names of the npm modules are consistent with the approach of creating npm packages.\n\n**Example**:\n```js\nmodules: {\n  local: [\n    '@test/my-local-module',\n    'users',\n  ],\n  npm: [\n    '@npm/npm-module',\n  ],\n}\n```\n\n### Module requirements\nEach module needs several things to work properly:\n\n#### `index.js` entry file:\n\nIn the project directory we create an entry file called `index.js`, needed to run the module.\n- `index.js` is created according to the [Nuxt Modules](https://nuxtjs.org/guide/modules/) rules,\n- The default exported function must be asynchronous,\n- We can add two additional functions:\n  - `beforeModule()` - asynchronous function run before the module is loaded,\n  - `afterModule()` - synchronous function started after the module is loaded,\n\n```js\nexport async function beforeModule() {\n    // run before loding module\n}\nexport default async function () {\n   // module logic\n}\nexport async function afterModule() {\n    // run after loding module\n}\n```\n\n#### `config` directory:\nModule must have a `config` directory with `index.js` file. All available configurations can be placed in this directory.\n\n##### **Configurations:**\n- `index.js`: Main configuration file exporting object:\n  - `name`: Module name\n    - Type: `String`\n    - Required: `true` :warning:\n  - `aliases`: Module aliases needed for easy communication between modules\n    - Type: `Object`\n    - Required: `true` :warning:\n  - `relations`: Modules relations. Modules in this array are needed for proper module operation.\n    - Type: `Array`\n    - Required: `false`\n  - `replacements`: Component replacements. Replace any component from any module with your own.\n    - Type: `Object`\n    - Required: `false`\n  - `plugins`: Module plugins loaded globally.\n    - Type: `Array`\n    - Required: `false`\n  - `css`: Module css loaded globally.\n    - Type: `Array`\n    - Required: `false`\n\n  **Example:**\n  ```js\n  export default {\n      name: '@test/core',\n      aliases: {\n          '@Core': '/',\n      },\n      replacements: {\n        '@Core/components/coreComponent': '/components/myComponent',\n      },\n      relations: [\n        '@test/messages',\n      ],\n      plugins: [\n          { ssr: true, src: './plugins/axios' },\n      ],\n      css: [\n          './assets/scss/reset.scss',\n      ]\n  };\n  ```\n\n- `routes.js`: Main routing configuration file for the module. Is closely related with [Nuxt Router](https://github.com/nuxt-community/router-module) mechanism.\n\n  **Example**:\n    ```js\n    const Page = () =\u003e import('@Core/pages/settings/index').then(m =\u003e m.default || m);\n    const Tab = () =\u003e import('@Core/components/tab').then(m =\u003e m.default || m);\n\n    export default [\n      {\n          name: 'settings',\n          path: '/settings',\n          component: Page,\n          children: [\n              {\n                  name: 'settings-main',\n                  path: 'main',\n                  component: Tab,\n              },\n          ],\n      },\n    ];\n    ```\n\n- `extends.js`: Mechanisms extending other modules.\n  - `extendComponents`: You can extend components from one module to components from another.\n    - Type: `Object`\n    - Required: `false`\n\n    **Example**:\n    ```js\n    // Definition\n    const Navigation: () =\u003e import('@Notifications/components/Navigation');\n\n    export default {\n      extendComponents: {\n        NAVIGATION_BAR: [\n          {\n            component: Navigation,\n            props: {},\n          },\n        ],\n      },\n    };\n    ```\n    The global `this.$getExtendSlot()` function is used to download the component.\n    ```js\n    // Use in other module\n    \u003ctemplate v-for=\"(component, index) in extenededComponents\"\u003e\n        \u003cComponent\n            :is=\"component.component\"\n            :key=\"index\"\n            v-bind=\"component.props\" /\u003e\n    \u003c/template\u003e\n    \u003cscript\u003e\n    export default {\n      computed: {\n        extendedComponents() {\n          return this.$getExtendSlot('NAVIGATION_BAR');\n        },\n      },\n    };\n    \u003c/script\u003e\n    ```\n  - `extendRoutesChildren`: You can extend routing in any module.\n    - Type: `Array`\n    - Required: `false`\n\n    **Example**:\n    ```js\n    const TestSettingsTab = () =\u003e import('@Test/components/SettingsTab').then(m =\u003e m.default || m);\n\n    export default {\n      extendRoutesChildren: [\n          {\n            name: 'settings', // existing router name what we want extend\n            children: [ // array with router to extend\n              {\n                name: 'settings-test',\n                path: 'test',\n                component: TestSettingsTab,\n              },\n            ],\n          }\n      ];\n    }\n    ```\n  - `dictionaries`: You can extend dictionaries.\n    - Type: `Array`\n    - Required: `false`\n\n    **Example**:\n    ```js\n    export default {\n        dictionaries: [\n            {\n                stateProp: 'currencies',\n                dataFormat: {},\n                requestPath: '/dictionary/currencies',\n            },\n        ]\n    }\n    ```\n  - `extendStore`: You can extend the existing Vuex store.\n    - Type: `Object`\n    - Required: `false`\n\n    **Example**:\n    ```js\n    const TestStore = () =\u003e import('@Test/extends/store/test');\n\n    export default {\n        extendStore: {\n            Test: TestStore,\n        },\n    }\n    ```\n    If we have existing `Test` store and we want extend it.\n\n  - `extendMethods`: You can insert any method from module\n    - Type: `Object`\n    - Required: `false`\n\n    **Example**:\n    ```js\n    // Definition\n    export default {\n        extendMethods: {\n            '@Test/store/test/action': () =\u003e {\n                console.log('test');\n            }\n        },\n    }\n    ```\n    The global `this.$getExtendMethod()` function is used for call extended methods.\n    ```js\n    // Use in other module\n    export default {\n        create({ state }) {\n            ...\n            this.$getExtendMethod('@Test/store/test/action');\n            ...\n        }\n    }\n    ```\n\n## Example application\n\n- [Ergonode](https://github.com/ergonode/frontend)\n\n\n[npm]: https://verdaccio.org/\n[verdaccio]: https://verdaccio.org/\n[vue]: https://vuejs.org\n[nuxt]: https://nuxtjs.org/\n[router]: https://github.com/nuxt-community/router-module\n[vuex]: http://vuex.vuejs.org\n[i18n]: https://i18n.nuxtjs.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fergonode%2Fvuems","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fergonode%2Fvuems","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fergonode%2Fvuems/lists"}