Tailwind CSS 按需加载依赖 JIT 模式、精准 content 配置和构建时代码分割三者协同;必须显式启用 mode: 'jit',content 覆盖所有模板路径(含 .vue/.mdx/.html),动态类名需 safelist 声明,组件级隔离靠 @apply + scoped/style modules,路由分包需构建工具配合且 content 包含异步组件路径,主题切换须枚举 safelist 而非宽泛正则,运行时动态加载 CSS 会破坏 Tree Shaking 并引发 FOUC。

Tailwind CSS 项目实现 CSS 按需加载,核心不是“手动引入某个类”,而是让构建工具只打包你真正用到的样式——jit 模式 + content 配置 + 构建时代码分割,三者缺一不可。其他所谓“运行时动态 import CSS”的做法,多数是伪按需,反而增加 FOUC 风险或破坏 Tree Shaking。
启用 JIT 模式并配准 content 路径
这是按需加载的底层前提。Tailwind v3+ 默认启用 JIT,但若项目仍用旧配置,必须显式确认:mode: 'jit' 已写入 tailwind.config.js(或 .ts)。更重要的是 content 数组必须精确覆盖所有可能写 Tailwind 类的地方:
-
./src/**/*.{js,jsx,ts,tsx,vue}—— 不要漏掉.vue或.mdx文件 -
./public/**/*.html—— 如果有服务端渲染或静态 HTML 模板 - 路径通配符必须真实存在,比如写了
./src/features/**/*却没这个目录,PurgeCSS 就会扫描不到对应文件,导致样式丢失 - 动态类名如
class={`${isRed ? 'text-red-500' : 'text-blue-500'}`必须通过safelist声明,否则会被误删
避免全局 import,改用组件级样式隔离
Tailwind 本身不支持“在组件里 import 一个 CSS 文件来加载部分类”。所谓“局部引入”本质是构建时静态分析的结果,不是运行时加载。真正有效的隔离方式是:
- 在 Vue 中使用
<style scoped>+@apply定义组件专属原子类,这些类会被content扫描捕获,且不会污染全局 - React 中配合 CSS Modules(
.module.css)或 styled-components,把@apply写进 JS 字符串,同样可被 Tailwind 解析 - 绝对不要在组件
<script>里写import './Button.css'并期望它只加载 Button 相关 Tailwind 类——这只会触发全量tailwind.css的重复加载
路由/页面级 CSS 分割需配合构建工具
想做到“访问 /dashboard 时才加载 dashboard 相关样式”,不能靠 Tailwind 自身,而要依赖 Webpack 或 Vite 的代码分割能力:
立即学习“前端免费学习笔记(深入)”;
- Vite 用户:在路由定义中使用动态
import(),并确保该路由组件内部使用的 Tailwind 类已被content覆盖;Vite 会自动为该 chunk 生成独立 CSS - Webpack 用户:配合
MiniCssExtractPlugin和splitChunks配置,将不同路由 chunk 的 CSS 提取为单独文件 - 关键陷阱:
content必须包含异步组件路径,例如./src/pages/**/*.{tsx},否则即使用了lazy(),Tailwind 也扫描不到那些文件里的类名,最终生成的 CSS 还是空的 - 不要试图用
import('xxx.css')在useEffect里加载样式——这会绕过构建时分析,导致样式缺失或 FOUC
主题切换与 safelist 的实际影响
动态主题(如 light/dark 切换)最容易暴露按需加载的盲区。Tailwind 不会运行时解析 class 字符串,所以 class="bg-${theme}-background" 这种写法必然失败:
-
safelist是唯一可靠方案,但别写太宽泛的正则,比如/bg-.*/会保留全部背景色类,体积暴增 - 更优解是枚举已知主题值:
{ pattern: /bg-(light|dark)-.*/ }或直接列出['bg-light-primary', 'bg-dark-primary'] - 使用
@layer把主题相关样式归到components层,并在对应页面组件中 import,这样它们只随该页面 chunk 加载 - 注意:CSS 变量(
var(--bg))无法被 PurgeCSS 识别,必须搭配safelist或预设 class 使用
真正的按需加载发生在构建阶段,不是运行时。任何试图用 JavaScript 动态插入 <link> 或 import() 加载 Tailwind 样式的操作,都违背了它的设计逻辑,容易引发样式错乱、FOUC 或 bundle 重复。最稳妥的做法,是让 content 配置足够精准,safelist 覆盖所有动态场景,再交由构建工具完成分包——其余都是干扰项。


















