tailwind v3+ jit 未生效主因是content路径未精准覆盖所有含class文件;需显式包含.tsx、.jsx、.vue等扩展名,避免./前缀,补充safelist应对动态类,并强制生产构建验证。

content 路径没配对,JIT 就等于没开
Tailwind v3+ 内置 PurgeCSS(即 JIT 编译器),但它的生效前提是 content 字段必须精准覆盖所有含 class 的文件。写成 ./src/**/*.{js,ts} 会漏掉 .tsx 和 .jsx;只写 src/App.tsx 却不加 src/components/**/*.tsx,子组件里的 className 就全被忽略——结果输出的 CSS 还是接近 2MB。
常见踩坑点:
- 路径带
./前缀:Vite、Next.js 等工具在某些环境下直接跳过匹配,建议统一用相对根路径写法,如src/**/*.{html,js,ts,tsx,jsx} - SSR/静态生成模板(如
pages/**/*.mdx、data/**/*.ejs)没进content→ 服务端渲染出的 class 不会被扫描,上线就丢样式 - 第三方组件库(如
react-datepicker)的 class 不在你源码里 → 必须显式加进safelist或把对应node_modules/xxx/**/*.js加入content(后者慎用,易反弹体积)
safelist 正则太宽泛,等于白配
动态类名(如 text-${color}、bg-${status}-500)不会被 JIT 解析,因为 Tailwind 只扫描字符串字面量。你得靠 safelist 手动兜底,但正则写错反而让 Purge 失效。
正确做法:
- 避免
/^bg-/这种无差别匹配:它会保留全部bg-*类,体积立马涨回几百 KB - 改用精确范围,例如
/^bg-(blue|gray|red)-[0-9]+$/或/^(text|bg)-(primary|secondary|success)$/ - 优先用
@apply封装语义类(如.btn-primary),再把该 CSS 文件路径加入content,比 safelist 更可控
别信 dev 服务器,强制走生产构建验证
开发模式下 JIT 是全量供应,npm run dev 看起来正常,不代表生产也 OK。真正检验配置是否生效,必须跑一次真实生产流程:
执行命令:TAILWIND_MODE=build npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify
验证方式:
- 检查输出文件大小:从 1.8MB 掉到 10–30KB 才算有效
- 用
grep -o "text-lg" dist/output.css | wc -l对比源码中出现次数,若远少于源码频次,说明 Purge 生效 - 临时在某个
.tsx文件里加一行className="bg-hotpink text-9xl"(非法值),再构建:如果输出 CSS 里真出现了bg-hotpink,说明 JIT 已退化为全量模式
和 Vite / Next.js 等工具集成时,插件顺序不能乱
Vite 用户容易忽略 vite-plugin-tailwind 的加载时机。如果它在 PostCSS 插件链里位置太靠后,或与 vite-plugin-react 冲突,会导致 JSX 中的 className 根本没被解析就进入 Purge 阶段。
推荐配置:
- Vite:确保
vite-plugin-tailwind在plugins数组中排在react()之后、css()之前 - Next.js:用官方
@next/font+tailwind.config.js默认配置即可,但需确认content包含app/**/*.{js,ts,jsx,tsx}和pages/**/*.{js,ts,jsx,tsx} - Webpack:若用
ts-loader,务必开启transpileOnly: false,否则 TSX 中的字符串字面量可能被 Babel 提前处理掉
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











