Vue.js和本地NPM软件包的应用程序模块化

时间:2020-07-25 09:25:09

标签: javascript vue.js npm vue-cli-3 modularity

我正在尝试通过vue-cli-service在Vue中构建模块化应用程序。主应用程序和模块是位于不同文件夹中的独立项目,其结构如下:

-- app/package.json
      /src/**
-- module1/package.json
          /src**
-- module2/package.json
          /src**

这个想法是让Vue应用程序完全不知道运行时可以使用的应用程序模块,这些模块本身是用vue-cli-service build --target lib编译到本地moduleX/dist文件夹中的,指向该软件包。 json“主要”和“文件”节点。

我的第一个想法(现在只是出于开发速度的目的)是将模块作为本地NPM软件包添加到应用程序中,使用观察程序进行构建,并使用观察程序本身为应用程序提供服务,以便对依赖模块进行任何更改(我认为)会自动分发到主应用程序。

因此,应用程序的package.json包含以下依赖项:

...
"module1": "file:../module1",
"module2": "file:../module2",
...

这种依赖关系意味着可以随时删除,或者通常根据需要进行组合,只需重新编译应用程序,一切都可以正常工作。

我现在正在尝试了解如何动态加载和激活应用程序中的模块,因为我不能像这样使用动态导入:

import(/* webpackMode: "eager" */ `module1`).then(src => {
    src.default.boot();
    resolve();
});

因为基本上我不知道'module1','module2'等...

在OOP世界中,我只会使用实现特定接口的依赖注入检索类,但是在JS / TS中,我不确定它是否可行。

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:1)

package.json玩杂耍对我来说不是一个好主意-无法扩展。我会做什么:

  1. 保留package.json中所有可用的“模块”
  2. 使用所有可用的配置(例如针对不同的客户端)创建单独的js文件(或在package.json内拥有自己的道具)
module.exports = {
   'default': ['module1', 'module2', 'module3'],
   'clientA': ['module1', 'module2', 'module4'],
   'clientB': ['module2', 'module3', 'module4']
}
  1. 进入VueCLI构建过程-我发现的最佳示例是here并创建js文件,该文件将在每次构建(或“服务”)并使用简单模板(例如lodash)生成新文件之前运行js文件,它将基于某些ENV变量的值引导已配置的模块。请参阅以下(伪)代码(请记住,此代码在构建期间在节点内运行):
const fs = require('fs')
const _ = require('lodash')
const modulesConfig = require(`your module config js`)

const configurationName = process.env.MY_APP_CONFIGURATION ?? 'default'
const modules = modulesConfig[configurationName]

const template = fs.loadFileSync('name of template file')
const templateCompiled = _.template(template)
const generatedJS = templateCompiled({ `modules`: modules })
fs.writeFileSync('bootModules.js', generatedJS)
  1. bootModules.js编写模板。最简单的是:
<% _.forEach(modules , function(module) { %>import '<%= module %>' as <%= module %><% }); %>;
  1. bootModules.js导入您的应用
  2. 使用MY_APP_CONFIGURATION ENV变量来切换所需的模块配置-不仅在开发过程中有效,而且您还可以使用不同的MY_APP_CONFIGURATION值针对相同的仓库设置不同的CI流程

这样,您可以将所有配置都放在一个位置,无需在每次构建之前更改package.json,您可以通过简单的机制在不同的模块配置之间切换,并且每个构建(捆绑)仅包含所需的模块....

答案 1 :(得分:0)

在OOP世界中,我只会使用实现特定接口的依赖注入检索类,但是在JS / TS中,我不确定它是否可行。

为什么不呢?

除此之外,对于JS / TS,您不限于使用实现特定接口的类:您只需要定义模块的接口(即module.exports)并在库条目中尊重它( vue build lib)。

编辑:阅读评论可能我理解了请求。

每个模块都应遵循以下接口(在vue库条目的文件中)

export function isMyAppModule() {
  return true;
}

export function myAppInit() {
  return { /* what you need to export */ };
}

比在您的应用中

require("./package.json").dependencies.forEach(name => {
  const module = require(name);

  if(! module.isMyAppModule || module.isMyAppModule() !== true) return;

  const { /* the refs you need */ } = module.myAppInit();

  // use your refs as you need
});