真正值得提取的是带语义的CSS自定义属性变量,如--primary-color;脚本应扫描CSS文件定位:root或@property声明及var()使用,按作用域分global、component、unused三类输出,并建议用PostCSS替代正则以准确解析复杂语法。

提取前先确认:你真正要的是变量,不是任意CSS规则
很多人误以为“提取公用样式”就是把所有重复的 color: #333 或 font-size: 14px 拿出来——但那只是表面重复,没解决维护问题。真正值得提取的,是带语义的变量,比如 --primary-color、--spacing-md 这类被多处 var(--xxx) 引用的自定义属性。否则提取完一堆散落的值,反而更难管理。
Node 脚本能做的,是扫描所有 .css 文件,定位 :root 块或 @property 声明,再收集所有 var(--xxx) 的使用位置。别指望它自动猜出哪些该合并——那是设计系统的事,脚本只负责“找出来、列出来、不漏掉”。
用正则 + fs.readdirSync 扫描全部 CSS 文件
别用 fs.readFile 逐个回调嵌套,容易失控。直接同步读取目录,再用正则匹配关键内容:
const cssFiles = fs.readdirSync('./src/styles').filter(f => f.endsWith('.css'))- 对每个文件,用
fs.readFileSync(path, 'utf8')读取字符串(不是 callback) - 提取变量声明:
/--\w+:\s*[^;]+;/g—— 注意它会捕获--color-primary: #007bff;这类整行 - 提取变量使用:
/var\(--\w+(?:\s*,\s*[^)]+)?\)/g—— 覆盖var(--color-primary)和var(--size, 1rem)
注意:这个正则不处理嵌套函数如 calc(var(--a) + var(--b)),如果项目里大量这么写,得换成 AST 解析(比如用 postcss),否则漏检。
立即学习“前端免费学习笔记(深入)”;
避免把不同作用域的变量混在一起
一个常见坑:把组件级 .card { --shadow: 0 2px 4px rgba(0,0,0,.1); } 和全局 :root { --shadow: ... } 全塞进同一个 variables.css。结果是组件样式一改,全局变量就冲突。
建议按作用域分三类输出:
-
global.css:仅含:root声明 + 被 3 个以上文件引用的var() -
component-variables.css:每个组件单独的--xxx,保留原作用域注释 -
unused.css:声明了但从没被var()调用的变量(说明已废弃)
判断“被引用次数”不能只靠文件数——得统计 var(--x) 在所有 CSS 中出现的总次数,低于 2 次的变量默认归入 unused.css。
PostCSS 插件比手写正则更可靠,但需额外安装
如果你的 CSS 里用了 @layer、@container 或嵌套语法,正则基本失效。这时直接上 postcss:
- 安装:
npm install postcss postcss-values-parser - 用
postcss.parse()解析 AST,遍历Declaration节点找prop.startsWith('--') - 用
postcss-values-parser安全解析var(--x, fallback)的参数结构
代价是启动慢一点,但不会把 background: var(--color, linear-gradient(...)) 里的逗号当分隔符切错。手写正则遇到这种 case,十次有八次崩。
真正麻烦的不是怎么提取,而是提取后没人 review —— 变量名是否语义清晰、fallback 是否统一、是否和设计系统文档对齐。脚本只能帮你把数据摊开,决策还得人来拍板。


















