UnoCSS默认不生成CSS,必须通过extractor静态提取class字符串才能触发按需生成;若HTML中class未被扫描到(如动态拼接、路径未配置、文件未覆盖),即使写了presetUno也不会输出对应规则。

UnoCSS 默认不生成 CSS?先确认 extractor 是否“看见” class
UnoCSS 不是写完 class 就自动出样式,它依赖 extractor 从源码中静态提取类名字符串。如果页面上写了 class="p-4 text-red-500" 却没生效,大概率是 extractor 没扫描到——不是配置错,而是它根本没读到这行 HTML。
常见漏提场景:
-
class值含插值:如 Vue 中class="p-4 {{ extra }}"、JSX 中className={`p-4 ${dynamic}`} - 类名藏在 JS 字符串或注释里:
// 这里有个 text-blue-600或console.log('m-2') - HTML 文件未被
content配置覆盖,比如用vite-plugin-html动态注入的 index.html 没加进扫描路径
验证方式:运行 unocss --inspect,打开 http://localhost:5000 查看实际提取了哪些类——比翻日志更直接。
启用 presetUno 是基础,但别只靠它
presetUno() 提供了最常用的原子类(flex、text-lg、bg-gray-100 等),但它本身不决定“哪些类该生成”,只定义“能生成哪些类”。真正触发生成的是 extractor 抓到的字符串是否匹配 preset 里的规则。
立即学习“前端免费学习笔记(深入)”;
所以即使你写了 presetUno(),若 extractor 没提取到 text-red-500,最终 CSS 里就不会有这条规则。
建议做法:
- 确保
uno.config.ts中presets至少包含presetUno() - 检查
content配置是否覆盖所有模板文件,例如:content: ['src/**/*.{html,vue,ts,tsx}'] - 避免把关键类名写在运行时拼接的变量里;若必须动态,优先改用
presetAttributify的属性写法(如text="red-500")
动态 class 怎么办?safeList 不是万能解药
当 class 确实无法静态提取(比如从 API 返回的样式名),可用 safeList 强制保底生成:
export default defineConfig({
safeList: [
'm-\d+',
'text-\w+-500',
'bg-[a-z]{3,}',
],
})
但要注意:
- 正则需转义特殊字符(如
d要写成\d) - 过度宽泛的 pattern(如
.*)会让按需优势失效,体积反弹 -
safeList是兜底手段,不是替代 extractor 的方案
更可持续的做法是收敛动态来源:把服务端返回的样式映射成有限枚举,再用 safeList: ['text-primary', 'text-secondary'] 显式声明。
小程序等多端项目必须切 per-module 模式
在 uni-app 或 Taro 等多端框架中,mode: 'global'(默认)会生成一个 uno.css 全局引入——这对 H5 有效,但小程序编译期拒绝运行时注入样式,直接白屏。
解决方法是显式启用模块化模式:
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
UnoCSS({
mode: 'per-module', // 关键
}),
],
})
此时每个 .vue 文件会生成对应 .wxss 或 .acss,样式作用域严格隔离。这个配置点极易被忽略,且错误无明确报错,只表现为“样式不生效”。
真正卡住人的,从来不是 preset 写不写得全,而是 extractor 能不能“看见”、构建流程能不能“分得清”、目标平台允不允许“动态挂载”——三者缺一不可。


















