微前端应用隔离时子应用样式被污染怎么办?
我在用qiankun做微前端时,发现父应用的全局样式影响了子应用的组件显示,比如子应用的按钮样式突然变成红色,但它的Less文件里没定义这个颜色。
尝试过在子应用配置里开启sandbox:sandbox: { styles: true },但问题依旧存在。子应用入口文件有加Vue.config.productionTip = false,也不行…
父应用的main.js里有引入全局样式:
#app button {
background: red !important;
font-size: 1.2em;
}
子应用的按钮类名是.unique-btn,但渲染后还是被父应用的#app button样式覆盖了,这该怎么彻底隔离样式呢?
#app button这种高优先级选择器的全局样式。首先得知道:CSS 的作用域不是靠框架自动隔离的,尤其是你父应用用了
#app button这种带 ID 的选择器,权重太高了,子应用根本扛不住。靠谱做法有两个方向:
一是改父应用的样式写法,别用 ID 选按钮这种野路子,换成类名限定,比如
.app-root button,然后配合子应用加一个 unique 的前缀容器,比如把整个子应用挂到.app-root button就不会影响子应用,除非你子应用自己也用了.app-root,但一般不会这么干。二是用 CSS 沙箱插件,比如
qiankun官方推荐的sanitizeStyle或者社区的qiankun-css-isolation插件,这类插件会在子应用挂载时,自动把子应用的样式包裹一层唯一前缀的标签,同时把子应用 DOM 节点加个随机类名,这样样式就只作用于子应用内部。不过得注意,这种方案对父应用引入的全局样式(比如你这种#app button)是无能为力的,它只能保护子应用自己的样式不被污染,但挡不住父应用的暴力覆盖。所以最根本的还是:别在父应用里写
#app button这种全局选择器,换成带命名空间的类名,比如.app-btn,然后通过 BEM 或 CSS Modules 的方式管理,这样子应用随便怎么玩都不会被你父应用的按钮样式带偏。如果实在改不了父应用(比如老项目),那只能在子应用入口加个脚本,把所有按钮都套一层容器,再用
scoped或:deep()(Vue3)手动限定作用域,但这种是临时补救,不是正道。总结一句话:样式隔离靠不了 sandbox,得靠规范写法 + 插件辅助。
具体改法就是在子应用的webpack.config.js里找到css loader配置,加上
modules: true,像这样:如果懒得改webpack,也可以在子应用的入口html文件里加个,然后把所有样式都限制在这个容器内,比如用scoped css或者手动加个前缀选择器。