UnoCSS在大型项目中变慢的主因是未配置content.include,导致默认扫描node_modules等无关目录;正确做法是显式声明源码路径,如include: ['src/*/.{vue,ts,html,md}']。

UnoCSS 在大型项目里变慢,90% 是因为默认扫描了 node_modules —— 它不是“配置错了”,而是根本没配 content.include,导致每次热更新都白扫几千个无关文件。
为什么加了 @unocss/vite 反而更卡?
Unocss 默认行为是扫描整个项目目录,包括 node_modules、dist/、tests/ 等。它不区分“源码”和“依赖”,只要文件匹配 **/*.{vue,ts,html} 就全盘解析——哪怕那个 node_modules/lodash-es 里的注释写着 class="text-sm",也会触发一次正则匹配。
- 中型项目(300+ 依赖)下,单次热更新扫描耗时常达 4–8 秒,内存峰值超 1GB
- 错误写法:
exclude: ['./node_modules']—— 路径不对,./会被忽略,实际没生效 - 正则排除写成
/node_modules/也不可靠:某些包路径含node_modules字符串(比如 mock 数据文件),可能误杀
只扫 src 和 packages,怎么写 content.include?
显式声明“只扫这些”,比拼命排除更稳、更快。Vite 插件和构建阶段会共用同一套路径规则,避免开发/构建行为不一致。
- 标准单包项目:
include: ['src/**/*.{vue,ts,tsx,html,md}'] - Monorepo 多包结构(如
packages/ui、packages/utils):include: ['src/**/*', 'packages/**/src/**/*.{vue,ts}'] - 禁用宽泛 glob:
**/*.ts会拉入scripts/或types/下无样式逻辑的文件,增加无效匹配 - 如果用了
vite-plugin-vue的template提取,确保.vue文件被包含,否则class="..."在 template 中不会被识别
动态类名场景下,safelist 比 rules 更实在
rules 只对硬编码字符串生效;一旦类名来自变量拼接、v-bind:class 或 className.split(' ').join(' '),Unocss 就无法静态分析,必须靠 safelist 提前兜底。
立即学习“前端免费学习笔记(深入)”;
- 常见漏写点:
safelist: ['md:flex', 'lg:text-xl', 'dark:bg-gray-800']—— 响应式或暗色模式类容易被漏 - 别用
['*']或[/^.*$/]:这等于关掉按需生成,体积爆炸 - 配合
shortcuts使用更安全:shortcuts: [['btn-primary', 'px-4 py-2 bg-blue-600 text-white']],这类复合类可直接进 safelist,不用拆解 - 构建前跑一次
unocss --safelist(如有 CLI)能导出当前已用类,可作 safelist 初始参考
重复选择器拖慢构建?minify 必须开
重复类名(如多个组件都写了 flex items-center)本身不影响运行时,但会让 Unocss 在生成阶段反复计算相同 CSS 规则,浪费 CPU 和内存。
- 开启
minify: true后,display: flex+justify-content: center+align-items: center会被合并为一条规则,而非三条 - 注意:minify 仅作用于最终输出 CSS,不影响开发时的 HMR 行为
- 若你用了自定义
transformers(如transformerDirectives),确保它们不干扰 minify 流程 —— 比如在 transformer 里动态插入类名,可能绕过 minify
最易被忽略的点:Vite 插件初始化时传的 content 配置,和你在 uno.config.ts 里写的必须完全一致。手动调用 unocss.transform() 时若漏传,开发环境能跑,构建产物却可能缺失样式。


















