unocss 减少 css 体积的核心是“不生成”未静态出现的类,但动态 class 拼接会导致提取失败;需通过 content 配置覆盖所有含 class 的文件、避免变量插值、优先用 shortcuts 或全量原子写法、慎用 safelist,并确保类名对 extractor 可见。

UnoCSS 减少 CSS 体积的核心不是“删”,而是“不生成”——没在源码中静态出现的类,压根不会进最终 CSS;但可维护性崩塌往往发生在你试图“绕过静态分析”时。
content 配置必须覆盖所有含 class 的文件路径
UnoCSS 默认只扫描 .html、.vue、.tsx 等后缀,但如果你的 HTML 是用 vite-plugin-html 注入的,或 JS 中有 el.className = 'm-4' 这类写法,它就看不见。
- 显式把 HTML 路径加进
uno.config.ts的content.files,比如['src/**/*.{html,js,ts,vue}'] - 用
unocss --inspect启服务,打开http://localhost:5000直接看哪些 class 被提取了、哪些漏了 - 别信 “Vite 插件自动处理”,Vite 的
include和 UnoCSS 的content是两套逻辑,以uno.config.ts为准
动态 class 拼接会让 UnoCSS 彻底失明
class="m-2 text-${color}" 或 className={`p-4 ${isActive ? 'bg-blue-500' : ''}`} 这类写法,UnoCSS 静态分析时根本无法展开变量,对应规则不会生成,运行时就变空白样式。
- 优先改用
shortcuts预定义组合:shortcuts: [['btn-primary', 'px-4 py-2 bg-blue-500 text-white rounded']] - 条件类拆成全量原子写法:
class="p-4 bg-blue-500 text-white rounded hover:bg-blue-600",哪怕多几行,也比运行时失效强 - 若真要动态绑定,启用
@unocss/preset-attributify,改用<div m="4" text="blue-600"> 语法,extractor 更容易识别 <h3>safeList 是临时止血,不是长期方案</h3> <p>有人为保动态 class 显示正常,直接往 <code>safeList里塞'm-${n}'或'text-${color}-500',结果是:所有m-1到m-999、所有 color 组合全被打包进来,体积暴增,原子化优势归零。-
safeList只适合极少数确定范围的兜底场景,比如'bg-gradient-to-r'这种没出现在模板里但又必须存在的类 - 如果项目里大量依赖
safeList才能跑通,说明代码写法和 UnoCSS 的静态前提冲突了,该重构的是 JS 拼接逻辑,不是加 safeList - 图标类同理:用
@unocss/preset-icons时,务必配include/exclude控制扫描范围,否则node_modules里的图标 JSON 全被扫,tree-shaking 失效
真正卡住人的从来不是配置怎么写,而是你写的 class 是否“对 extractor 可见”——它不执行 JS,不解析 Vue 响应式,只认字符串字面量。想省体积又不掉链子,就得让 class 在构建时“站得出来”。
-











