微前端子应用如何正确加载公共样式而不冲突?
我在用 qiankun 搭建微前端项目,主应用和子应用都用了 Ant Design,但子应用的样式总是被主应用覆盖,导致 UI 错乱。我试过把子应用的样式 scoped,但有些全局组件(比如 Modal)还是出问题。
现在子应用入口 HTML 是这样写的:
<html>
<head>
<link rel="stylesheet" href="/static/antd.css" rel="external nofollow" />
</head>
<body>
<div id="subapp"></div>
</body>
</html>
有没有靠谱的方案能隔离子应用的样式,又不影响它自己的组件渲染?
最稳的方案是给主应用和子应用分别设置不同的 prefixCls,从根源上避免类名冲突。
主应用入口配置:
子应用入口配置:
然后子应用的 webpack 配置里也要改,确保样式类名一致:
如果你用的是 qiankun,记得在 registerMicroApps 的时候开启样式隔离作为兜底:
strictStyleIsolation 用的是 Shadow DOM,Ant Design 的弹窗组件会直接废掉。experimentalStyleIsolation 是通过给样式加选择器前缀实现的,配合 prefixCls 双保险。
还有个细节,子应用的 HTML 模板里那个 antd.css 的 link 标签可以删了,让 qiankun 按 JS 入口去加载,不然那个 link 标签加载的样式类名还是 ant 开头的,白搭。
先说配置,主应用启动时加上:
但这只是第一步,真正麻烦的是 Ant Design 的全局组件。Modal、Message、Notification 这些东西默认挂载到 body 上,根本不在子应用的容器里,样式隔离对它们无效。
按照 Ant Design 官方文档的做法,需要配置
ConfigProvider的prefixCls和getPopupContainer:prefixCls 改了之后,样式也得跟着改。webpack 里配置 less 变量:
还有个问题,你 HTML 里手动写的那个 link 标签要删掉。qiankun 的规范是样式由子应用的入口 JS 动态注入,写在 HTML 里加载时机不可控,很容易被主应用后加载的样式覆盖。
总结一下要做的事:主应用开启 experimentalStyleIsolation,子应用配置 ConfigProvider 的 prefixCls 和 getPopupContainer,webpack 里设置 @ant-prefix 变量,删掉 HTML 里的手动样式引用。这套组合拳下来基本就稳了,我们这边十几个子应用跑了一年多没出过问题。