远程组件的样式隔离

背景

在做工作台应用中,整个页面是由远程组件组成的(如下图),远程组件本质上是打包了vue组件,然后通过 requirejs 动态加载组件并且注册到页面上。 所以本身会带来跟微前端很类似的问题。

  1. Js没隔离。 组件可以修改window对象、组件内部也可以重写内置对象方法... ❌
  2. css没隔离。 组件内的样式不加scoped的话,样式各种污染...
    下面这种图很清晰的展示了组件A、组件B都有一个.containerclass命名,并且没有scoped的话。一个设置了背景色为red,一个设置了blue。这样的话就会产生污染。而且跟随网络加载状态,后注册的远程组件的样式将优先级更高。

思考

微前端的CSS隔离主要有两种:

  1. 样式增加不同前缀
  2. ShadawDom

这里毫无疑问增加不同前缀是最简单、最快的方式了。

解决(配置)

分解

要想把组件内的css都加个前缀的话,要自己在编译时做处理那就是很麻烦的事情(投入产出比不是很高),所以第一反应还是去找编译Vue时候有没有入口。我们是Vite+Vue3项目,项目中配置如下

json 复制代码
// ...其他配置
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === 'micro-app'
        }
      },
      include: [/\.vue$/, /\.md$/], // <--
    }),
    // ...其他配置
  ],

查看@vitejs/plugin-vue配置

可以很敏感的发现有一个自定义的template配置。那必然还有一个style配置了。果然是有(如下图)。然后查看SFCStyleCompileOptions。当看到postcssPlugins时候,就可以直接飞起了。postcss插件。css界的Babel.

ts 复制代码
export declare interface SFCStyleCompileOptions {
    source: string;
    filename: string;
    id: string;
    scoped?: boolean;
    trim?: boolean;
    isProd?: boolean;
    inMap?: RawSourceMap;
    preprocessLang?: PreprocessLang;
    preprocessOptions?: any;
    preprocessCustomRequire?: (id: string) => any;
    postcssOptions?: any;
    postcssPlugins?: any[];
    /**
     * @deprecated use `inMap` instead.
     */
    map?: RawSourceMap;
}

寻找插件并配置。

那现在的问题就是寻找postcss插件,postcss生态还是很好的。 postcss-prefix-selector。然后进行配置。组件内的css都加了属性选择器作为前缀 [data-hurricane-code="${组件ID}"]

json 复制代码
 plugins: [
    extractElComponentsPlugin(),
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === 'micro-app'
        }
      },
      include: [/\.vue$/, /\.md$/], // <--
      style: {
        postcssPlugins: [
          postcssPrefixSelector({
            prefix: `[data-hurricane-code="${COMPONENT}"]`, // 添加前缀选择器
            exclude: [/\.portal-ignore/],
            includeFiles: [`${resolve(__dirname, '../packages')}`]
          })
        ]
      }
    }),
  ],

查看编译后结果

css 复制代码
.table{
  width: 100%;
}
.swwwwww {
  background-color: red;
  height: 100px;
}

=> 
[data-hurricane-code=TestSww] .table[data-v-394bd0c5] { 
   width: 100%; 
}
[data-hurricane-code=TestSww] .swwwwww[data-v-394bd0c5] { 
    background-color: red; height: 100px; 
 }

现在变成这样隔离了。

但是有些需要忽略的,可以根据规则自定义传入忽略的className。可以自行配置。

相关推荐
GISer_Jing7 分钟前
前端开发:提示词驱动的全链路
前端·javascript·aigc
辛-夷10 分钟前
TS封装axios
前端·vue.js·typescript·vue·axios
Swift社区23 分钟前
Vue Router 越写越乱,如何架构设计?
前端·javascript·vue.js
大布布将军26 分钟前
⚡️ 后端工程师的护甲:TypeScript 进阶与数据建模
前端·javascript·程序人生·typescript·前端框架·node.js·改行学it
程序员小易1 小时前
前端轮子(1)--前端部署后-判断页面是否为最新
前端·vue.js·node.js
xiaoxue..1 小时前
列表转树结构:从扁平列表到层级森林
前端·javascript·算法·面试
小oo呆1 小时前
【自然语言处理与大模型】LangChainV1.0入门指南:核心组件Agent
前端·javascript·easyui
Hao_Harrision2 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨ | DrawingApp(画板组件)
前端·react.js·typescript·tailwindcss·vite7
dly_blog2 小时前
Vite 原理与 Vue 项目实践
前端·javascript·vue.js
计算机毕设VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue汽车销售系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·汽车·课程设计