2

所以我正在努力将我公司的应用程序迁移到微前端方法。我们遵循https://micro-frontends.org/中描述的标准。虽然目前一切都在使用 React,但我们正在使用 Web Components 进行包装,以便我们在未来拥有与框架无关的自由和灵活性。我们已经建立并运行了一个工作架构,到目前为止它运行良好。我们甚至在 Web 组件规范之上创建了一个花哨的兼容性层,它允许我们将类似 React 的 props 传递给 Web 组件,包括对象、数组甚至函数。这允许它们之间更好的交互。

我们现在主要关心的是库的重复。我们是一家 React 商店,所以即使我们有这种与框架无关的方法,一切都在使用 React。虽然这种新方法使我们能够将应用程序的各个部分单独升级到更新的 React 版本(最终),但我们仍然不喜欢 React 库的如此多重复的想法。

换个角度来看,即使是 Gzipped,React/ReactDOM 也超过 40kb。单独来说这是非常小的,但按比例放大它开始占用越来越多的带宽。RAM 方面问题不大,这些库大约 130kb,鉴于现在大多数设备的 RAM 容量,这并不是什么大问题。

但是,当然,我们希望事情尽可能优化和简化。所以我希望有人可以为微前端应用程序(包装在 Web 组件中的应用程序)提出一种方法,以便从父应用程序中获取 React 和其他库。

您应该知道父应用 JavaScript 在微前端之前加载。每个微前端都通过<script>标签加载。最后,我们目前没有使用 Shadow DOM,这是我们为了将现有代码迁移到新的微前端架构而做出的权衡。

4

2 回答 2

2

核心思想是告诉模块捆绑器如何打包你的微前端。

假设你使用 Webpack 来打包你的应用程序,这里有两件事你需要做。

步骤1:

像在Webpack 配置中一样将React 声明为外部依赖项:

externals: {
  'react': 'React',
  'react-dom': 'ReactDOM'
},

第2步:

React在加载父应用程序的 JS 之前,请确保ReactDOM从 CDN 或其他等效位置加载:

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

将这些脚本放在index.html负责引导整个 SPA 的主脚本中。

解释

当您将某个包/库声明为外部时,Webpack 不会将其作为捆绑包的一部分。它假定外部环境将使该特定版本可用作全局变量。在 React 的情况下,它使用ReactReactDOM作为全局变量。

通过这样做并通过 CDN 包含它,您将只剩下一份ReactReactDOM。当用户第一次访问应用程序时,它会变慢,但一旦缓存,应该没有问题

此外,您可以扩展此想法并将它们声明为父应用程序父外壳容器外部

于 2019-06-12T15:37:25.510 回答
1

可能的解决方案是使用 Import Map 准备库,但由于它不支持 IE11+,我建议您使用 SystemJS?

https://github.com/systemjs/systemjs

特别是这个似乎接近你的情况:

https://github.com/systemjs/systemjs-examples/tree/master/loading-code/react-hello-world

在 html 你做:

  <script type="systemjs-importmap">
    {
      "imports": {
        "react": "https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js",
        "react-dom": "https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"
      }
    }
  </script>
  <script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.min.js"></script>

然后你可以导入 ReactJS,因为浏览器知道从哪里获取它。

有可能构建某种库来查看您的微前端(MFE)package.json,以了解需要使用哪个库并动态创建类似于上面示例的导入对象。

我们需要记住,需要涵盖版本检查。提到的库可能会存储某种映射,它将依赖关系与版本与可访问的位置联系起来。想象一下,如果提到我们需要在每个 MFE 上处理不同的反应版本 :)。

然后在加载另一个 MFE 库时可以检查是否已包含所需的依赖项,如果缺少某些依赖项,请下载它,否则使用已获取的内容。

另一件事是使用带有模块联合的 webpack 5,我还没有推荐它,因为它对于生产来说不够稳定,但有可能开始使用它。困难的部分将涵盖版本检查,因此很可能需要另一个抽象层来处理它。

https://indepth.dev/webpack-5-module-federation-a-game-changer-in-javascript-architecture/

于 2020-07-27T10:00:14.203 回答