Vite 插件:CSS 作用域隔离,解决微前端和模块联邦中的样式冲突问题
npm install @jiayouzuo/vite-plugin-css-scopeVite 插件:CSS 作用域隔离,解决微前端和模块联邦中的样式冲突问题。
- CSS 选择器包裹:.btn → [data-scope-appProcess="1"] .btn
- JSX 自动注入:自动给模块联邦暴露的组件父元素添加作用域属性
- HTML 自动注入:自动给 添加作用域属性
- Portal 容器处理:自动处理 antd Modal、Drawer、Dropdown、Select、Tooltip、Message、Notification 等全局挂载组件
- 智能过滤:自动跳过 :root、html、body、@keyframes 等全局选择器
- HOC 支持:支持 forwardRef、memo 等高阶组件
- 多格式支持:CSS、Less、SCSS、Sass、JSX、TSX
``bash`
npm install @jiayouzuo/vite-plugin-css-scope -D或
pnpm add @jiayouzuo/vite-plugin-css-scope -D
`typescript
// vite.config.ts
import { defineConfig } from 'vite';
import cssScopePlugin from '@jiayouzuo/vite-plugin-css-scope';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
// ⚠️ 重要:cssScopePlugin 必须放在 react 插件之前
cssScopePlugin({
scope: 'appProcess', // 作用域名称
include: ['src/', 'node_modules/@designable/'], // 要处理的目录
exclude: ['node_modules/antd'] // 排除的目录(可选)
}),
react()
]
});
`
| 参数 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| scope | string | 是 | 作用域名称,会生成 data-scope-{scope}="1" 属性选择器 |include
| | string[] | 是 | 要处理的目录列表(相对于项目根目录) |exclude
| | string[] | 否 | 排除的目录或文件 |
`css
/ 原代码 /
.btn { color: red; }
.card, .panel { padding: 10px; }
/ 转换后 /
[data-scope-appProcess="1"] .btn { color: red; }
[data-scope-appProcess="1"] .card, [data-scope-appProcess="1"] .panel { padding: 10px; }
`
配合模块联邦使用时,暴露的组件会自动注入作用域逻辑:
`jsx
// 原代码
function FormDesigner() {
return 表单设计器;
}
// 自动转换后
function FormDesigner() {
const __scopeRefCallback = (__el) => {
if (__el) {
const __parent = __el.parentElement;
if (__parent && !__parent.hasAttribute("data-scope-appProcess")) {
__parent.setAttribute("data-scope-appProcess", "1");
}
}
};
return (
<>
$3
`html
`$3
antd 的 Modal、Drawer、Dropdown、Select、Tooltip、Message、Notification 等组件会将弹层挂载到
document.body,插件会自动处理这些 Portal 容器:-
@rc-component/portal - Modal、Drawer
- rc-trigger - Dropdown、Select、Tooltip、Popover 等
- rc-notification - Message、Notification$3
`css
/ 这些选择器保持原样,不会被包裹 /
:root { --color: red; }
html { font-size: 16px; }
body { margin: 0; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
`适用场景
1. 模块联邦样式隔离:主应用(antd 5.x)和远端应用(antd 4.x)样式冲突
2. 微前端样式隔离:多个子应用样式互不干扰
3. 第三方组件库隔离:如 @designable 等组件库的样式隔离
工作原理
1. CSS 处理:使用 PostCSS 遍历所有规则,给选择器外层包裹
[data-scope-xxx="1"] 属性选择器
2. JSX 处理:使用 Babel AST 解析,注入回调 ref,通过辅助 div 获取父元素并添加作用域属性
3. HTML 注入:通过 Vite 的 transformIndexHtml 钩子给 ` 自动加上作用域属性MIT