Tailwind CSS生产包体积过大主因是content字段未配全或未走生产构建导致JIT失效;须精确覆盖所有含class文件路径、为动态类加safelist正则兜底,并用TAILWIND_MODE=build验证裁剪效果。

原子类没关 JIT 或 on-demand 模式,打包体积直接翻倍
Tailwind、UnoCSS 默认开启全量类生成时,哪怕 HTML 里只用了 text-sm 和 flex,最终 CSS 文件也会包含全部 10,000+ 个工具类。这不是“多写点 class”的问题,是构建产物里塞进了根本用不到的 mt-[999px]、bg-gradient-to-tr 这类边缘规则。
后果很实在:首屏 CSS 体积从 80KB 涨到 420KB,LCP 延迟 300ms+,CI 构建时间多出 12 秒。团队新人照着文档跑 npx tailwindcss -i ./src/input.css -o ./dist/output.css,结果上线就崩性能。
- 必须在
tailwind.config.js中显式启用content配置,指向所有含 class 的文件路径(src/**/*.{js,ts,jsx,tsx,html}) - UnoCSS 用户得确认
content选项已启用,并禁用preflights(除非真需要重置样式) - Webpack/Vite 插件若未正确注入扫描逻辑,
content配置形同虚设
JS 动态拼接 class 字符串,生产环境样式神秘消失
常见错误现象:className={`p-${size} ${isDisabled ? 'opacity-50 cursor-not-allowed' : ''}`} 在本地正常,上线后 p-4 有,opacity-50 却没了——PurgeCSS 扫不到字符串模板里的变量值,直接删掉。
这不是 bug,是设计使然。原子化框架依赖静态分析,而 JS 拼接等于主动绕过扫描器。
立即学习“前端免费学习笔记(深入)”;
- 所有可能出现在运行时的 class 名,必须显式列在
content的 glob 模式中,或通过safelist硬编码(如['opacity-50', 'cursor-not-allowed']) - 避免用数字变量驱动间距类:
mt-${n}比mt-[7px]更危险,前者会触发全量mt-0到mt-96打包 - Vue 的
:class、React 的clsx同样适用该规则,没有例外
多人同时改同一段 HTML,class 冲突不报错但语义失效
两个人在不同 PR 里给同一个按钮加 class:PR#123 加了 bg-blue-600 hover:bg-blue-700,PR#125 又叠了 bg-indigo-600 disabled:bg-gray-300。合并后按钮禁用时背景是灰色,但悬停色却消失了——因为 bg-indigo-600 覆盖了 hover:bg-blue-700 的基础色,而 hover 规则本身还在,只是颜色没变。
这种冲突不会触发 ESLint 报错,DevTools 里也只显示一堆 class,没人能一眼看出哪条规则被悄悄覆盖。
- 必须启用
eslint-plugin-tailwindcss的no-custom-classname规则,禁止手写非框架类名(如my-btn) - 高频组合应提前收编进
@layer components,例如定义.btn-primary { @apply bg-blue-600 hover:bg-blue-700 ... },让多人操作落在同一语义锚点上 - 禁用自由组合的团队规范要落地到 PR 模板里:“新增原子类组合前,请先查
@layer components是否已有对应语义类”
设计师改色值/间距,前端全局搜索替换却漏掉 CSS-in-JS 和内联 style
设计系统把主色从 #3B82F6 改成 #2563EB,前端 grep 全项目 blue-500 替换为 blue-600,结果发现按钮在某个 React 组件里还是旧蓝——因为那里用了 Emotion 的 css`background: #3B82F6`,或者直接写了 style={{ backgroundColor: '#3B82F6' }}。
原子化方案只管自己的 class 生态,对其他样式来源完全无感。一旦项目混用多种样式方案,维护边界就模糊了。
- 约定优先级:组件内样式 → Tailwind class;跨组件通用状态(如 loading)→ CSS-in-JS 的
styled.div+:is()伪类 - 禁用内联 style,所有动态样式走 class 控制(
className={loading ? 'opacity-50' : ''}) - CI 阶段用正则扫描
css`.*#[0-9A-Fa-f]{6}`和style=.*#[0-9A-Fa-f]{6},发现即 fail
flex 或 gap-4,而是所有人同步关闭 JIT、所有人敬畏 content 配置、所有人接受“不能随便拼字符串”。最容易被忽略的,是以为开了 Tailwind 就自动安全——其实它只提供工具,不提供纪律。


















