UnoCSS热更新失效主因是缓存未失效、content路径漏扫新文件或注入时机错位;需检查content是否覆盖所有class位置、enforce: 'pre'配置、mode: 'vue-scoped'显式设置及transformer-attributify的ignore配置。

热更新时 UnoCSS 规则没实时渲染,基本不是插件坏了,而是构建流程里某个环节“卡住”了变更信号——最常见的是缓存未失效、扫描路径漏掉新文件、或注入时机错位。
为什么 vite dev server 不触发 UnoCSS 重生成
Vite 的 HMR(热模块替换)默认只通知 .vue 或 .ts 文件变化,但 UnoCSS 的规则生成依赖对 class 字符串的静态扫描。如果新增类名只出现在刚创建的组件、未被 content 配置覆盖的文件(比如 src/views/xxx.vue 没进 glob),Vite 就不会把该文件纳入 UnoCSS 的重扫描范围。
-
content路径必须显式包含所有可能写 class 的位置,例如['src/**/*.{vue,ts,js,html}'],不能只写src/**/* - 新增文件若在开发中被创建,但 Vite 进程已启动,需手动触发一次
import 'uno.css'所在模块的 HMR(比如改下main.ts空行)才能拉起全量重扫描 - 使用
@unocss/vite时,插件必须配置enforce: 'pre',否则 Vue 插件可能先处理 SFC,导致<template></template>内容还没吐给 UnoCSS 就被编译掉了
为什么改了 class 却看到旧样式(尤其 scoped 场景)
Vue 组件启用 scoped 后,UnoCSS 必须知道这个上下文才能生成带 [data-v-xxx] 属性的选择器。如果 mode: 'vue-scoped' 没在 uno.config.ts 中显式设置,它仍按全局规则生成,而全局规则优先级低于组件内 <style scoped></style>,浏览器就直接忽略。
- 仅靠 Vite 插件自动推断
vue-scoped模式不可靠,必须手动写死mode: 'vue-scoped' - 动态类名如
:class="`text-${color}`"不会被扫描,热更时改color值,UnoCSS 根本不知道要生成哪个新规则——这类情况只能靠@unocss/transformer-directives或提前枚举 - 如果用了
transformer-attributify,又没配ignore: ['v-if', 'v-model'],它可能把指令当类名误处理,导致规则污染和 HMR 错乱
Webpack 5 下热更新失效的隐藏原因
Webpack 5 的持久化缓存(cache.type = 'filesystem')会缓存 unplugin 的 transform 结果。UnoCSS 的即时编译本质是“每次扫描都应重新计算”,但缓存可能把上一次的 CSS 输出锁死了,连带跳过后续的注入逻辑。
立即学习“前端免费学习笔记(深入)”;
- 临时解决:启动时加
--no-cache,确认是否缓存导致;长期方案是在webpack.config.js中为 UnoCSS 相关 loader 设置cache: false -
style-loader的injectType设为'singletonStyleTag'时,它复用同一个<style></style>标签,但 UnoCSS 新生成的规则若没触发该标签内容更新(比如 CSS 文本没变),DOM 就不会刷新 - 检查控制台是否有
[UnoCSS] No matching rules—— 这说明扫描阶段已失败,热更再多次也无济于事
真正难排查的是“看似更新了,但规则没进 DOM”的情况:它往往卡在扫描 → 生成 → 注入三个环节中的任意一个,且每个环节的失败表现都一样——页面没变。盯住控制台日志、检查生成的 uno.css 内容、比对浏览器 Elements 面板里 <style></style> 标签的实际文本,三者缺一不可。


















