@jiayouzuo/css-scope-vite
v0.1.8
Published
Vite插件:通过hash前缀实现CSS作用域隔离,解决模块联邦中的样式冲突
Downloads
851
Maintainers
Readme
@jiayouzuo/css-scope-vite
Vite插件:通过hash前缀实现CSS作用域隔离,解决模块联邦中的样式冲突问题。
核心场景
在模块联邦(微前端)架构中,主应用和远端应用可能使用不同版本的antd,导致样式冲突:
主应用(antd 5.x):.ant-btn { color: blue; }
远端应用(antd 4.x):.ant-btn { color: red; }
→ 样式互相覆盖!使用本插件后:
主应用:.ha1b2c3d-ant-btn { color: blue; }
远端应用:.he5f6g7h-ant-btn { color: red; }
→ 完全隔离!支持的库
- antd 4.x / 5.x
- @designable/react (低代码设计器)
- @formily/antd (通过 antd 的 ConfigProvider 自动支持)
- 用户自定义的 CSS 类名
安装
npm install @jiayouzuo/css-scope-vite -D
# 或
pnpm add @jiayouzuo/css-scope-vite -D使用
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import cssScopePlugin from '@jiayouzuo/css-scope-vite'
export default defineConfig({
plugins: [
// ⚠️ 重要:cssScopePlugin 必须放在 react() 之前!
cssScopePlugin({
scope: '[hash:8]', // hash长度,默认8位
projectId: 'my-app', // 项目标识,用于生成唯一hash
include: [
'src/', // 处理用户代码
'node_modules/antd/', // 处理antd的CSS和JS
'node_modules/@designable/' // 处理@designable的CSS和JS
],
exclude: [] // 排除的目录(可选)
}),
react()
]
})为什么必须放在 React 插件之前?
Vite插件按数组顺序执行。本插件需要处理原始的JSX代码来识别和替换className:
// 原始JSX代码
<div className="header-box">
// cssScopePlugin处理后
<div className="ha1b2c3d-header-box">
// 最后由react()编译成
React.createElement("div", { className: "ha1b2c3d-header-box" })如果react()先执行,JSX会被编译成React.createElement调用,本插件就无法识别className属性了。
配置选项
| 选项 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| scope | string | 是 | - | hash格式,如 [hash:8] |
| projectId | string | 否 | package.json的name | 项目标识,用于生成唯一hash |
| include | string[] | 是 | - | 需要处理的目录列表 |
| exclude | string[] | 否 | [] | 排除的目录列表 |
include 配置说明
重要:只有在 include 中配置的路径才会被处理,包括:
- CSS/Less 文件的选择器转换
- JSX/TSX 文件的 className 转换
- antd/@designable 的 prefixCls 修改
include: [
'src/', // 用户代码
'node_modules/antd/', // antd 的 CSS 和 JS
'node_modules/@designable/' // @designable 的 CSS 和 JS
]如果只配置了 'src/',则 antd 和 @designable 的样式不会被处理。
工作原理
- CSS处理:使用PostCSS给所有类选择器添加hash前缀
- JS处理:
- 用户代码:使用Babel替换className字符串
- antd:修改
defaultPrefixCls变量 - @designable:修改
Layout.defaultProps.prefixCls
- Hash生成:
'h' + md5(projectId).slice(0, hashLength)
转换示例
/* 原CSS */
.ant-btn { color: blue; }
.dn-app { background: #fff; }
.header-box { padding: 10px; }
/* 转换后 */
.ha1b2c3d-ant-btn { color: blue; }
.ha1b2c3d-dn-app { background: #fff; }
.ha1b2c3d-header-box { padding: 10px; }/* 原JSX */
<div className="header-box">
<Button className="my-btn">
/* 转换后 */
<div className="ha1b2c3d-header-box">
<Button className="ha1b2c3d-my-btn">注意事项
- 与CSS Modules互斥,不能同时使用
- 处理第三方库会增加构建时间
- DevTools中看到的是带hash的类名
- 修改
include配置后需要清除node_modules/.vite缓存
调试
启动时控制台会输出:
[css-scope-plugin] 项目ID: my-app, Hash前缀: ha1b2c3dLicense
MIT
