Tailwind CSS v3+默认启用JIT,Vite中热更新失效主因是配置链断裂:@tailwindcss/vite插件绕过PostCSS实时注入class,但要求@import "tailwindcss"必须首行、禁用动态拼接、启用devSourcemap并配合vite-plugin-inspect验证。

Tailwind CSS v3 及以上版本默认启用 JIT(Just-in-Time)模式,Vite 项目里它天然就工作——但热更新不生效、样式不刷新、改了 class 没反应,基本不是 JIT 本身的问题,而是加载链或配置没对齐。
为什么 @tailwindcss/vite 插件能直接开 JIT 热更新
传统 PostCSS 方式需要 tailwind.config.js 中声明 content 路径,靠文件扫描 + PurgeCSS 剔除未用样式;而 @tailwindcss/vite 插件在 Vite 的模块解析阶段就介入,把 HTML/JSX/Vue 模板里的 class 字符串实时喂给 Tailwind 引擎,JIT 编译器当场生成对应 CSS 并注入 HMR 流程。不需要 purge,也不依赖 content 字段。
关键点:
-
@tailwindcss/vite是 Vite 官方推荐的轻量路径,不走 PostCSS,不读postcss.config.js - JIT 编译发生在开发时(dev),不是构建时(build),所以改 class → 触发 HMR → 新 CSS 注入 DOM,全程无刷新
- 插件自动处理 Vue
<template></template>、React.tsx中的静态 class,但不分析动态拼接(如:class="`bg-${color}`")
@import "tailwindcss" 必须是 CSS 文件第一行
这是最常导致“JIT 有但热更新不触发”的静默失败点。Vite 的 CSS 加载器会把 @import 当作预处理指令,如果前面有注释、空行、其他 @import,整个 Tailwind 解析就会跳过,后续所有 class 都不会被识别。
立即学习“前端免费学习笔记(深入)”;
正确写法(src/style.css):
@import "tailwindcss"; @import "./base.css";
错误写法:
/* reset */ @import "tailwindcss";
或:
@import "./vars.css"; @import "tailwindcss";
注意:即使你用 CSS Modules(xxx.module.css),@import "tailwindcss" 仍需放在最顶行,否则该文件里写的全局类(如 text-red-500)不会生效。
动态 class 和模板字符串会让 JIT “看不见”
JIT 模式依赖静态分析,插件只提取字面量字符串中的 class 名。一旦 class 是运行时拼出来的,JIT 就无法预判,对应样式不会生成,热更新自然也无从谈起。
这些写法会导致样式丢失:
- Vue:
:class="'bg-' + color + ' text-white'" - React:
className={`p-${size} ${isActive ? 'bg-blue-500' : 'bg-gray-200'}`} - 任何用
eval、new Function或模板字符串嵌套变量的 class 组合
可行替代方案:
- 提前定义完整类名数组:
const classes = ['bg-red-500', 'bg-blue-500', 'text-white'],再用classes.includes(myClass)控制 - 用
clsx或twMerge这类工具库,它们在构建期可被插件识别(需确认插件支持) - 对高频动态组合,手动在
tailwind.config.js的theme.extend.safelist中显式保留(仅限少量)
Vite 配置里别漏掉 css.devSourcemap: true
虽然不影响 JIT 编译逻辑,但缺少源映射会让浏览器开发者工具里看不到 class 对应的真实 CSS 规则来源,调试时只能看到 style 标签内联样式,无法定位到是哪个 HTML 元素触发的生成,排查热更新卡点非常吃力。
建议在 vite.config.ts 中加这一项:
export default defineConfig({
css: {
devSourcemap: true
}
})
配合 vite-plugin-inspect(安装后访问 http://localhost:3000/__inspect/),你能直接看到 JIT 实时生成了哪些 CSS 规则,以及哪些 class 被识别、哪些被忽略——这才是 JIT 热更新真正可验证的证据。
真正容易被忽略的是:JIT 不是魔法,它依赖 Vite 的模块图和插件链完整性。哪怕只是多了一行空注释,或者用了 .jsx 而不是 .tsx,都可能让 class 分析中断,热更新就断在第一步。



















