如何使用 Webpack 创建与容器应用程序共享库的微前端包? [英] How to create a Micro Frontend bundle with Webpack that shares libraries with the container application?

查看:26
本文介绍了如何使用 Webpack 创建与容器应用程序共享库的微前端包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个任务.

拥有带有单spa框架的微前端.

To have Micro Frontends with single-spa framework.

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

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

So my problem just one: I don't want to duplicate vendor libraries like react, react-dom (any others). And I want to make them shared among other Micro Frontends (which is bundled with webpack)

我知道拥有一些全局内容是什么不好的做法(这违反了与 webpack 捆绑的整个想法).但是如何解决厂商库重复的问题?

I know what is the bad practice to have some global stuff (it's violate the whole idea of bundeling with webpack). But how to solve the problem of duplication of vendor libraries?

我发现一个解决方案只是使用 SystemJs 加载规范,例如 html 中的分隔标签,但我只是想知道也许还有另一种解决方案.

I found one solution just load decencies with SystemJs like separated tags in html, but I just wonder maybe there is another solutuion for that.

谢谢.

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

SystemJs approach to load dependencies by demand but from CDN, I just want do the same but load all dependencies from "shared" webpack bundle with react and other stuff.

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)
}

推荐答案

更新:

刚刚意识到,您的问题是针对 Micro Frontends(不仅是微服务),因此不是关于一般与 Webpack 共享库.将微前端添加到您的标签/标题并更新了答案,使其更加关注此主题.

Just realized, that your question is directed at Micro Frontends (not only micro services) and therefore is not about sharing libraries with Webpack in general. Added Micro Frontend to your tags/title and updated the answer to be more focused on this topic.

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

So my problem just one: I don't want to duplicate vendor libraries like react, react-dom (any others). And I want to make them shared among other [Micro Frontends] (which is bundled with webpack)

你可以做的是通过添加一个 Webpack externals 配置的属性.

What you can do is exclude dependencies from the output bundle of your Micro Frontends by adding a Webpack externals property to the config.

微前端的 webpack 配置:

webpack config of your Micro Frontends:

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

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

Above config would exclude react and react-dom and expect them in the global variables React and ReactDOM. You can then share those dependencies by including the libraries in a script inside index.html of your root applicationn aka stitching layer:

<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>

如果您有其他通用组件要共享,您还可以将库脚本集成到 组件库.

If you have other common components to share, you can also integrate the library scripts in a component library.

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

The reason for the include as script is: We do not want that our container has to require/import the Micro Frontends at build time in order to avoid a coupling of build/release/version management between all apps. Instead one purpose of Micro Frontends is to achieve fully independent deployment of the parts, which include continuous delivery steps from build, test to release.

我知道拥有一些全局内容是什么不好的做法(这违反了与 webpack 捆绑的整个想法).

I know what is the bad practice to have some global stuff (it's violate the whole idea of bundeling with webpack).

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

Of course, you create some form of coupling between the apps. But if you have a mature, stable and common library shared by all parts, it is a reasonable decision.

希望(现在)有帮助!

这篇关于如何使用 Webpack 创建与容器应用程序共享库的微前端包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆