qiankun样式污染问题的讨论

1,667 阅读4分钟

一、背景

现在没有哪家公司不使用微前端来进行作为项目的组织架构了。

但是这个东西的出现也带来了新的问题。

比如说各个业务团队使用的UI框架不一样的时候,就会导致如下这样的样式污染。

image.png

样式的污染,css-scoped或者css module解决了绝大部分,但是对于多子应用同时加载,主子应用之间的冲突,导致了所有的弹窗样式都是有问题的。

二、解决方案

使用qiankun沙盒模式隔离

这是一个坑。神光最近也写过相关的文章,想要详细的了解,可以自寻查找。下面我简单的总结一下:

  • qiankuncss 沙箱的原理是重写 HTMLHeadElement.prototype.appendChild 事件,记录子项目运行时新增的 style/link 标签,卸载子项目时移除这些标签。

思路就是将子项目的样式局限到子项目的容器范围,不在这个范围样式不生效。但是对于一些弹窗就无能为力了,它们需要挂载到 body 上面,不在子应用容器中,样式就无法生效。

  • 使用换肤的思路来解决 :在子项目给 body 加一个唯一的 idclass),在对应的全局的样式前面加上这个 id/class。而 single-spa 模式则在 mount 周期给 body/html 加上这个唯一的 id/class,在 unmount 周期去掉,这样就可以保证这个全局 css 只对这个项目生效了。

这两个方案的致命点都在于无法解决多个子项目同时运行时的 css 污染,以及子项目对主项目的 css 污染。

这两个方案已经能够把绝大多数问题解决。但是我们的项目中,是有一个看板的业务的。看板的业务就会把多个子应用同时加载。如果使用上面的两种方案,那么谁的包大,谁加载得慢,那么body的id/class就归谁的。物尽天择?

添加自定义命名空间

如果使用了element plus版本的简单很多了。2.20版本以上的,详情可以点击element-plus.gitee.io/zh-CN/guide…

核心代码如下:

// styles/element/index.scss
// we can add this to custom namespace, default is 'el'
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
  $namespace: 'ep'
);
// ...

使用postcss-plugin-namespace插件添加自定义命名空间

其他版本就需要借助插件来实现自定义命名空间了。有很多可以实现相同功能的插件,下面我以插件为例子。

npm i postcss-plugin-namespace -D

在根目录创建postcss.config.js 文件。

module.exports = (ctx) => {
  return {
    plugins: [
      require('postcss-plugin-namespace')('#lee_project', {
        ignore: [
          'html', /body/, 'span', 'el-form-item', /[data/,
        ]
      }),
    ]
  }
}

ignore顾名思义就是忽略的class,也可以使用正则,如 /body/ 。里面有一个data,这是使用了style scroped之后,会给节点上面添加data-xxxx 。所以它也需要忽略掉。

直接覆盖样式

我劝你不要冲动,这是我们统计一部分样式污染的class名称:

image.png

主应用使用了和子应用不同的UI框架。我们为了让样式在加载我的应用的时候,需要全局复写上面的这些class名,并放在全局。

上面这些污染的class只是冰山一角哦,可自行评估一下需要多少工时。

三、容易疏忽的问题

字体属于静态资源。项目肯定是开启了协商缓存的。所以说,加载过之后的静态资源也是会污染全局的。而这个时候我们就需要处理两个问题。

自己从iconfont中下载下来的字体图标

直接修改iconfont的前缀即可。如下图配置:

image.png

element ui 内置的图标

并没有搞明白为什么什么的插件没有自动添加修改前缀。所以我们使用了最暴力的解决办法。不用element ui内置的图标,全部替换成iconfont的。问题解决就行。

这是因为我们项目的图标很少,所以能够这样干。如果你项目中有大量的图标的话,还是想想怎么使用插件来解决吧。解决了求求教教我。求求了!

四、总结

  • 编程没有银弹,引入的qiankun解决了多团队协作的问题,也带来了新的问题。但是也要有我们在做技术选项的时候要有这样的心理预期。
  • 自定义命名空间本质依旧是约定样式规范。

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天, 点击查看活动详情