我有几个微前端 React 应用程序。 所有应用程序都与技术无关。这意味着任何应用程序都可以将任何库作为依赖项。 他们正在使用 webpack 模块联合插件。如果其他微前端应用程序中的版本相同,则将共享依赖项。
微前端应用分为:主微前端应用和子微前端应用。 主应用程序是其他子应用程序的容器。一次只能运行一个子应用程序。
我们公司有带有react组件的UI-Kit。库包括 CSS 变量、全局选择器(* {/* CSS 规则 */})。
子应用可以依赖我们的 UI-Kit。如果 UI-Kit 的版本不同,其中一个子应用程序可能会应用错误的样式。 工作流程(工作原理):我在浏览器中打开主应用程序,webpack 加载主应用程序首页的所有资源(JS、CSS、字体)。之后我打开带有 Sub app 1 的页面,webpack 加载 Sub app 1 的资源并将其插入到文档中(CSS 样式将插入到文档的头部)。 我们的 UI-kit 有 CSS 模块,但这还不够,因为类的名称不是根据 CSS 规则的内容创建的。此外,CSS 变量可能会在其中一个版本中更改。此外,子应用可能不会使用我们的 UI-Kit,但是来自 UI-Kit 的所有 * CSS 规则将应用于此子应用。此外,两个子应用程序可以使用不同版本的同一个库,这个库可以使用全局或模块 CSS。
我需要为每个微前端应用程序应用完整的 CSS 隔离。
上次我尝试应用支持完全 CSS 隔离的影子 DOM。但是其中一个库(cytoscapejs 或其插件)调用了 document.getElementById 方法。它返回 null,因为它正在寻找的元素已经在影子根中。我正在调查这个案子。
在此之前,我考虑过为我们的 UI-Kit 添加一个版本到 CSS 模块类的末尾。但它不会使 CSS 变量的名称唯一。 此外,我认为我无法从我的微前端应用程序构建中重命名外部库的 CSS 类。
此外,我知道 style-loader 可以允许使用“use”和“unuse”方法添加和删除样式标签。我可以用它来防止覆盖两个子应用程序的样式。但是 mini-css-extract-plugin 没有这个功能。
我可以尝试使用 :has 和 :not 选择器,但我不想处理许多不同的 CSS 案例(* 选择器、css 变量等)。我认为这是错误的方式。
checkout PostCss Prefix Wrap 插件 将选择器添加到 CSS 样式有助于防止 CSS 从一个微前端泄漏到另一个微前端。
为了使用插件安装它并像这样扩展你的 webpack.config:
npm i postcss-prefixwrap
const PrefixWrap = require('postcss-prefixwrap')
...
...
{
loader: 'postcss-loader',
options: {
sourceMap: true,
postcssOptions: {
plugins: [
PrefixWrap('#mfe_id_<appname>', {
nested: '&',
})],
},
},
}
请遵守#mfe_id_ 命名并将相同的 ID 添加到 MFE 中最顶层的元素。
优势
缺点