9

我有一个任务。

拥有单水疗框架的微前端。

  1. 门户/主应用程序(通过 url 加载所有其他 js 代码)
  2. 微前端 1(基于反应)
  3. 微前端 2(基于反应)

所以我的问题只有一个:我不想复制像 react、react-dom (任何其他)这样的供应商库。我想让它们在其他微前端(与 webpack 捆绑)中共享

我知道拥有一些全球性的东西是什么不好的做法(它违反了与 webpack 捆绑的整个想法)。但是如何解决供应商库的重复问题呢?

我发现一个解决方案只是使用 SystemJs 加载体面,例如 html 中的分隔标签,但我只是想知道是否还有另一种解决方案。

谢谢你。

SystemJs 方法通过需求加载依赖项,但从 CDN,我只想做同样的事情,但从“共享”webpack 包加载所有依赖项,并带有 react 和其他东西。

window.SystemJS = window.System

function insertNewImportMap(newMapJSON) {
  const newScript = document.createElement('script')
  newScript.type = 'systemjs-importmap'
  newScript.text = JSON.stringify(newMapJSON)
  const allMaps = document.querySelectorAll('script[type="systemjs-importmap"]')

  allMaps[allMaps.length - 1].insertAdjacentElement(
    'afterEnd',
    newScript
  )
}

const devDependencies = {
  imports: {
    react: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.development.js',
    'react-dom': 'https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.development.js',
    'react-dom/server': 'https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom-server.browser.development.js',
    'single-spa': 'https://unpkg.com/single-spa@4.3.2/lib/umd/single-spa.min.js',
    lodash: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js',
    rxjs: 'https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.js',
  }
}

const prodDependencies = {
  imports: {
    react: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js',
    'react-dom': 'https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js',
    'react-dom/server': 'https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom-server.browser.production.min.js',
    'single-spa': 'https://unpkg.com/single-spa@4.3.2/lib/umd/single-spa.min.js',
    lodash: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js',
    rxjs: 'https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js',
  }
}

const devMode = true // you will need to figure out a way to use a set of production dependencies instead
if (devMode) {
  insertNewImportMap(devDependencies)
} else {
  insertNewImportMap(prodDependencies)
}

4

2 回答 2

6

更新:

刚刚意识到,您的问题是针对微前端(不仅是微服务),因此通常与 Webpack 共享库无关。在您的标签/标题中添加了微前端并更新了答案以更加关注这个主题。


所以我的问题只有一个:我不想复制像 react、react-dom (任何其他)这样的供应商库。我想让它们在其他 [Micro Frontends](与 webpack 捆绑)中共享

你可以做的是通过在配置中添加一个Webpack 外部属性来从你的微前端的输出包中排除依赖项。

微前端的 webpack 配置:

module.exports = {
  ...
  externals = {
    react: 'React',
    'react-dom': 'ReactDOM'
  }
}

上面的配置将在全局变量中排除react并期望它们和. 然后,您可以通过在根应用程序(即拼接层)内的脚本中包含库来共享这些依赖项:react-domReactReactDOMindex.html

<html>
  ...
  <body>
    ...
    <script src="<your-host>/react.prod-16.9.0.min.js"></script>
    <script src="<your-host>/react-dom.prod-16.9.0.min.js"></script>
  </body>
</html>

如果您有其他常用组件要共享,也可以将库脚本集成到组件库中。

包含脚本的原因是:我们不希望我们的容器在构建时需要/导入微前端,以避免所有应用程序之间的构建/发布/版本管理耦合。相反,微前端的一个目的是实现部件的完全独立部署,其中包括从构建、测试到发布的持续交付步骤。

我知道拥有一些全球性的东西是什么不好的做法(它违反了与 webpack 捆绑的整个想法)。

当然,您会在应用程序之间创建某种形式的耦合。但如果你有一个成熟、稳定、各部分共享的通用库,那是一个合理的决定。

希望,它有帮助(现在)!

于 2019-08-06T11:32:47.240 回答
2

今天实现这一点的最佳方法是使用 Webpack 在 v5 中发布的新模块联合技术。这种方法不使用 SystemJS,而是使用 Webpack 的内部。我们尝试了几种不同的微前端方法,但是这一种比它们都更出色,并且目前在生产中为我们成功运行。设置它肯定有一些挑战,但值得开发人员提高生产力。

这是创建者 Zack Jackson 制作的信息站点,它应该提供您需要的所有资源:https ://module-federation.github.io/

这是 webpack 文档的链接,它更多地处理技术问题,而不是如何实际设置完整的微前端架构:https ://webpack.js.org/concepts/module-federation/

于 2020-11-21T18:20:20.720 回答