jit 模式按需生成 css,仅编译实际使用的类名,开发时体积小、热更新快,但依赖 content 配置准确;动态拼接类名无效,safelist 非最优解,必须确保所有模板路径被 content 覆盖。

因为 JIT 模式不预生成所有工具类,只在你真实写出的 class 字符串上动态生成对应 CSS 规则——它不是“删掉没用的”,而是“只造你用的”。体积从 1.8MB 降到 12KB 不是压缩,是根本没生成那 1.7MB 的冗余代码。
为什么开发环境也能看到体积变小?
JIT 在开发服务器(如 npm run dev)中实时监听文件变化,每次保存后只解析当前 content 路径下被修改的文件,提取其中静态出现的类名,然后即时编译出最小 CSS。这和生产构建不同:它不依赖一次全量扫描,而是增量、按需、内存中完成。
- 开发时 CSS 体积小,是因为你当前页面/组件里只写了
text-lg、bg-blue-500这几个类,JIT 就只输出这几条规则 - 它不关心
tailwind.config.js里配了多少theme.spacing或screens,那些没被引用的断点、尺寸、颜色值完全不会出现在 CSS 中 - 热更新快的本质是:不用重扫整个项目,只 re-parse 变更文件的 AST,毫秒级响应
content 配置错误会让开发环境“假装正常”
开发服务器的 JIT 是宽松模式:即使 content 路径漏了,它也会 fallback 到部分缓存或默认兜底逻辑,所以本地 npm run dev 看起来一切正常——但这恰恰掩盖了问题。真正构建时,它会严格按 content 扫描,漏掉的路径里写的类直接消失。
- 典型错误:
content: ["./src/**/*.{ts,tsx}"]→ 漏掉.jsx文件,React 函数组件里的className="hover:bg-gray-100"不会被捕获 - 危险写法:
content: ["./**/*"]→ 扫到node_modules里压缩后的 JS,AST 解析失败,JIT 退化为保守全量输出 - 验证方式:在某个被
content覆盖的文件里加一句className="bg-hotpink",然后运行TAILWIND_MODE=build npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify,再grep "bg-hotpink" ./dist/output.css;为空才说明 JIT 真生效
动态类名拼接在开发环境也失效,只是你没立刻发现
JIT 基于静态 AST 分析,对运行时拼接无能为力。像 className={`p-${padding}`} 这种写法,在开发环境看似有样式,其实是浏览器缓存或旧 CSS 残留造成的错觉——刷新硬加载或清缓存后,p-4、p-6 等规则根本不在输出里。
-
tw`text-${color}-500`同样无效,除非color是字面量字符串(如tw`text-red-500`),且该行被 AST 正确提取 - 不要靠
safelist兜底所有可能值,比如/^p-[1-9]$/看似安全,但会保留全部p-1到p-9,而你实际只用了p-4和p-6 - 真正解法是把高频组合抽成自定义类:
.btn-primary { @apply py-2 px-4 bg-blue-600 text-white; },并确保该 CSS 文件路径加入content
最常被忽略的一点:JIT 的“按需”是严格基于你手写的字符串字面量,不是基于配置、不是基于变量推导、也不是基于运行时逻辑。哪怕只少配一个 .html 文件路径,或者漏掉 app/layout.tsx,暗色模式类、group-hover、甚至基础 flex 都可能在线上突然消失——而开发环境永远给你一种“它在工作”的幻觉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











