tailwind jit 体积失控主因是 content 路径配置不全,导致静态扫描失效而退化为全量输出;需覆盖所有模板路径、显式声明动态类、禁用开发模式验证、避免 html 手写冗长 class。

content路径没配全,JIT根本没启动
Tailwind v3+ 的体积控制完全依赖 content 数组的静态扫描,配错、漏写、带 ./ 前缀,都会让 JIT 退化为全量输出——你看到的 2MB+ CSS 就是它在“保守兜底”。
-
content: ["src/**/*.{js,ts}"]→ 漏了.jsx和.tsx,React 组件里的所有className全部失效 -
content: ["./src/**/*.{js,jsx,ts,tsx}"]→ 点号前缀在 Vite/Next.js 中可能被跳过,app/layout.tsx或pages/_app.tsx里的dark:类直接消失 - 用了 MDX、EJS、.html.ejs 模板?没加
src/content/**/*.mdx或views/**/*.html.ejs→ SSR 渲染出的 class 不在扫描范围,JIT 只能全留 - Next.js 项目只写了
app/**/*却漏掉pages/**/*→group-、peer-、aria-这类上下文工具类大概率丢失
动态类名没兜底,上线就丢样式
JIT 不执行 JS,只匹配源码中出现的字面量字符串。变量拼接(如 text-${color}-500)在构建时无法推断,不显式声明就会被当成“死代码”删掉。
- 优先用
@apply封装:在src/styles/components.css里写.btn-primary { @apply bg-blue-600 text-white; },再把该路径加进content - 必须保留动态拼接时,在
tailwind.config.js的safelist中写精确正则,例如/^text-(red|blue|green)-500$/,结尾加$防止误匹配text-red-5000 - 避免
/^text-/这种宽泛正则——它会保住全部text-类,体积直接反弹 - 第三方组件库(如
react-datepicker)的 class 不在你源码中 → 显式加进safelist,别往content里塞node_modules路径,容易引发体积反弹
没走生产构建,验证全是假象
开发服务器(npm run dev)是 JIT 实时供应,完全不依赖 content 扫描,也不触发 tree-shaking。你看到的体积毫无参考价值。
- 真正要验证的,是
TAILWIND_MODE=build npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify的输出 - 人工注入一个冷门但合法的类:在某个被
content覆盖的文件里加className="bg-hotpink",构建后运行grep -o "bg-hotpink" ./dist/output.css;如果命中,说明 JIT 已退化为全量模式 - Vite 用户可用
rollup-plugin-visualizer查看最终 CSS chunk 构成,确认tailwind.css是否真的被裁剪 - 检查高频类是否真被压缩:对比
grep -o "text-lg" ./src/**/*.tsx | wc -l和grep -o "text-lg" ./dist/output.css | wc -l,后者远少才代表生效
HTML里手写长类名,gzip也压不住膨胀
Tailwind 本身不增大 HTML,但反复手写 class="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100" 这类长串,会让首屏 HTML 直接多出 KB 级冗余字符,SSR 场景下更明显。
- 用
@apply提取语义类:如.card { @apply p-6 bg-white rounded-xl shadow-sm; },对应 HTML 变成<div class="card">,从 60+ 字符降到 8 字符 <li>必须确保该 CSS 文件路径加入 <code>content,比如"./src/styles/**/*.css",否则 JIT 不生成规则,样式直接丢失 - 别在
@apply里嵌套另一个@apply,Tailwind 会报错Cannot resolve @apply for - 框架组件封装更彻底:把类名逻辑收进 React/Vue 组件内部,HTML 层只传
variant="primary",连 class 属性都隐藏掉
真正卡住体积优化的,往往不是配置项本身,而是 content 路径是否覆盖了所有运行时真实渲染的模板——包括 SSR 输出的 .mdx、.ejs、服务端生成的 HTML 片段。这些地方一旦漏扫,JIT 就只能选择“全留”或“全删”,而它默认选前者。











