tailwindcss-performance

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Tailwind CSS Performance Optimization

Tailwind CSS性能优化

v4 Performance Improvements

v4版本性能改进

Tailwind CSS v4 features a completely rewritten engine in Rust:
Metricv3v4
Full buildsBaselineUp to 5x faster
Incremental buildsMillisecondsMicroseconds (100x+)
EngineJavaScriptRust
Tailwind CSS v4采用了完全用Rust重写的引擎:
指标v3v4
完整构建基准水平最高快5倍
增量构建毫秒级微秒级(快100倍以上)
引擎JavaScriptRust

JIT (Just-In-Time) Compilation

JIT(即时)编译

How JIT Works

JIT工作原理

JIT generates styles on-demand as classes are discovered in your files:
  1. Scans source files for class names
  2. Generates only the CSS you use
  3. Produces minimal, optimized output
JIT会在检测到文件中的类名时按需生成样式:
  1. 扫描源文件查找类名
  2. 仅生成你使用的CSS
  3. 生成最小化、经过优化的输出

v4: Always JIT

v4:默认启用JIT

Unlike v3, JIT is always enabled in v4—no configuration needed:
css
@import "tailwindcss";
/* JIT is automatic */
与v3不同,v4中JIT始终启用——无需配置:
css
@import "tailwindcss";
/* JIT自动启用 */

Content Detection

内容检测

Automatic Detection (v4)

自动检测(v4版本)

v4 automatically detects template files—no content configuration required:
css
/* v4 - Works automatically */
@import "tailwindcss";
v4会自动检测模板文件——无需配置内容路径:
css
/* v4版本 - 自动生效 */
@import "tailwindcss";

Explicit Content (v4)

显式指定内容(v4版本)

If automatic detection fails, specify sources explicitly:
css
@import "tailwindcss";
@source "./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}";
@source "./components/**/*.{js,jsx,ts,tsx}";
如果自动检测失败,可显式指定源文件:
css
@import "tailwindcss";
@source "./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}";
@source "./components/**/*.{js,jsx,ts,tsx}";

Excluding Paths

排除路径

css
@source not "./src/legacy/**";
css
@source not "./src/legacy/**";

Tree Shaking

树摇优化

How It Works

工作原理

Tailwind's build process removes unused CSS:
Source: All possible utilities (~15MB+)
Scan: Find used class names
Output: Only used styles (~10-50KB typical)
Tailwind的构建过程会移除未使用的CSS:
源文件:所有可用工具类(约15MB+)
扫描:查找已使用的类名
输出:仅包含已使用的样式(通常约10-50KB)

Production Build

生产环境构建

bash
undefined
bash
undefined

Vite - automatically optimized for production

Vite - 自动针对生产环境优化

npm run build
npm run build

PostCSS - ensure NODE_ENV is set

PostCSS - 确保设置NODE_ENV环境变量

NODE_ENV=production npx postcss input.css -o output.css
undefined
NODE_ENV=production npx postcss input.css -o output.css
undefined

Dynamic Class Names

动态类名

The Problem

问题所在

Tailwind can't detect dynamically constructed class names:
javascript
// BAD - Classes won't be generated
const color = 'blue'
className={`text-${color}-500`}  // ❌ Not detected

const size = 'lg'
className={`text-${size}`}  // ❌ Not detected
Tailwind无法检测动态拼接的类名:
javascript
// 错误写法 - 类名将不会被生成
const color = 'blue'
className={`text-${color}-500`}  // ❌ 无法被检测到

const size = 'lg'
className={`text-${size}`}  // ❌ 无法被检测到

Solutions

解决方案

1. Use Complete Class Names

1. 使用完整类名

javascript
// GOOD - Full class names
const colorClasses = {
  blue: 'text-blue-500',
  red: 'text-red-500',
  green: 'text-green-500',
}
className={colorClasses[color]}  // ✓ Detected
javascript
// 正确写法 - 使用完整类名
const colorClasses = {
  blue: 'text-blue-500',
  red: 'text-red-500',
  green: 'text-green-500',
}
className={colorClasses[color]}  // ✓ 可被检测到

2. Use Data Attributes

2. 使用数据属性

javascript
// GOOD - Style based on data attributes
<div data-color={color} className="data-[color=blue]:text-blue-500 data-[color=red]:text-red-500">
javascript
// 正确写法 - 基于数据属性设置样式
<div data-color={color} className="data-[color=blue]:text-blue-500 data-[color=red]:text-red-500">

3. Safelist Classes

3. 安全列表类名

css
/* In your CSS for v4 */
@source inline("text-blue-500 text-red-500 text-green-500");
css
/* 在v4版本的CSS中配置 */
@source inline("text-blue-500 text-red-500 text-green-500");

4. CSS Variables

4. CSS变量

css
@theme {
  --color-dynamic: oklch(0.6 0.2 250);
}
html
<div class="text-[var(--color-dynamic)]">Dynamic color</div>
css
@theme {
  --color-dynamic: oklch(0.6 0.2 250);
}
html
<div class="text-[var(--color-dynamic)]">动态颜色</div>

Optimizing Transitions

过渡效果优化

Use Specific Transitions

使用特定过渡属性

html
<!-- SLOW - Transitions all properties -->
<button class="transition-all duration-200">

<!-- FAST - Only transitions specific properties -->
<button class="transition-colors duration-200">
<button class="transition-transform duration-200">
<button class="transition-opacity duration-200">
html
<!-- 性能差 - 过渡所有属性 -->
<button class="transition-all duration-200">

<!-- 性能优 - 仅过渡特定属性 -->
<button class="transition-colors duration-200">
<button class="transition-transform duration-200">
<button class="transition-opacity duration-200">

GPU-Accelerated Properties

GPU加速属性

Prefer
transform
and
opacity
for smooth animations:
html
<!-- GOOD - GPU accelerated -->
<div class="transform hover:scale-105 transition-transform">

<!-- GOOD - GPU accelerated -->
<div class="opacity-100 hover:opacity-80 transition-opacity">

<!-- SLOW - May cause repaints -->
<div class="left-0 hover:left-4 transition-all">
优先使用
transform
opacity
实现流畅动画:
html
<!-- 性能优 - GPU加速 -->
<div class="transform hover:scale-105 transition-transform">

<!-- 性能优 - GPU加速 -->
<div class="opacity-100 hover:opacity-80 transition-opacity">

<!-- 性能差 - 可能导致重绘 -->
<div class="left-0 hover:left-4 transition-all">

CSS Variable Usage

CSS变量使用

Prefer Native Variables

优先使用原生变量

In v4, use CSS variables directly instead of
theme()
:
css
/* v3 - Uses theme() function */
.element {
  color: theme(colors.blue.500);
}

/* v4 - Use CSS variables (faster) */
.element {
  color: var(--color-blue-500);
}
在v4版本中,直接使用CSS变量而非
theme()
函数:
css
/* v3版本 - 使用theme()函数 */
.element {
  color: theme(colors.blue.500);
}

/* v4版本 - 使用CSS变量(更快) */
.element {
  color: var(--color-blue-500);
}

Static Theme Values

静态主题值

For performance-critical paths:
css
@import "tailwindcss/theme.css" theme(static);
This inlines theme values instead of using CSS variables.
针对性能关键路径:
css
@import "tailwindcss/theme.css" theme(static);
此配置会将主题值内联,而非使用CSS变量。

Build Optimization

构建优化

Vite Configuration

Vite配置

javascript
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [tailwindcss()],
  build: {
    // Minify CSS
    cssMinify: 'lightningcss',
    // Optimize chunks
    rollupOptions: {
      output: {
        manualChunks: {
          // Split vendor CSS if needed
        }
      }
    }
  }
})
javascript
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [tailwindcss()],
  build: {
    // 压缩CSS
    cssMinify: 'lightningcss',
    // 优化代码块
    rollupOptions: {
      output: {
        manualChunks: {
          // 按需拆分第三方CSS
        }
      }
    }
  }
})

PostCSS with cssnano

结合PostCSS与cssnano

javascript
// postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
    cssnano: process.env.NODE_ENV === 'production' ? {} : false
  }
}
javascript
// postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
    cssnano: process.env.NODE_ENV === 'production' ? {} : false
  }
}

Reducing Bundle Size

减小包体积

1. Avoid Unused Plugins

1. 避免加载未使用的插件

css
/* Only load what you need */
@plugin "@tailwindcss/typography";
/* Don't load unused plugins */
css
/* 仅加载需要的插件 */
@plugin "@tailwindcss/typography";
/* 不加载未使用的插件 */

2. Limit Color Palette

2. 限制颜色调色板

css
@theme {
  /* Disable default colors */
  --color-*: initial;

  /* Define only needed colors */
  --color-primary: oklch(0.6 0.2 250);
  --color-secondary: oklch(0.7 0.15 180);
  --color-gray-100: oklch(0.95 0 0);
  --color-gray-900: oklch(0.15 0 0);
}
css
@theme {
  /* 禁用默认颜色 */
  --color-*: initial;

  /* 仅定义需要的颜色 */
  --color-primary: oklch(0.6 0.2 250);
  --color-secondary: oklch(0.7 0.15 180);
  --color-gray-100: oklch(0.95 0 0);
  --color-gray-900: oklch(0.15 0 0);
}

3. Limit Breakpoints

3. 限制断点

css
@theme {
  /* Remove unused breakpoints */
  --breakpoint-2xl: initial;

  /* Keep only what you use */
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
}
css
@theme {
  /* 移除未使用的断点 */
  --breakpoint-2xl: initial;

  /* 仅保留需要的断点 */
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
}

Caching Strategies

缓存策略

Development

开发环境

  • v4's incremental builds are already extremely fast
  • No additional caching needed in most cases
  • v4的增量构建已经极快
  • 大多数情况下无需额外缓存

CI/CD

CI/CD流程

yaml
undefined
yaml
undefined

GitHub Actions example

GitHub Actions示例

  • name: Cache node_modules uses: actions/cache@v4 with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
  • name: Build run: npm run build
undefined
  • name: 缓存node_modules uses: actions/cache@v4 with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
  • name: 构建项目 run: npm run build
undefined

Measuring Performance

性能测量

Build Time Analysis

构建时间分析

bash
undefined
bash
undefined

Time your build

统计构建耗时

time npm run build
time npm run build

Verbose output

详细输出日志

DEBUG=tailwindcss:* npm run build
undefined
DEBUG=tailwindcss:* npm run build
undefined

Bundle Analysis

包体积分析

bash
undefined
bash
undefined

Install analyzer

安装分析工具

npm install -D vite-bundle-analyzer
npm install -D vite-bundle-analyzer

Analyze bundle

分析包体积

npm run build -- --analyze
undefined
npm run build -- --analyze
undefined

CSS Size Check

CSS大小检查

bash
undefined
bash
undefined

Check output CSS size

查看输出CSS文件大小

ls -lh dist/assets/*.css
ls -lh dist/assets/*.css

Gzipped size

查看Gzip压缩后的大小

gzip -c dist/assets/main.css | wc -c
undefined
gzip -c dist/assets/main.css | wc -c
undefined

Performance Checklist

性能检查清单

Development

开发环境

  • JIT is working (styles update instantly)
  • No console warnings about large files
  • Hot reload is fast
  • JIT正常工作(样式即时更新)
  • 控制台无大文件警告
  • 热重载速度快

Production

生产环境

  • NODE_ENV=production
    is set
  • CSS is minified
  • Unused CSS is removed
  • No dynamic class name issues
  • CSS size is reasonable (<50KB typical)
  • 已设置
    NODE_ENV=production
  • CSS已压缩
  • 未使用的CSS已移除
  • 无动态类名问题
  • CSS大小合理(通常小于50KB)

Common Issues

常见问题

IssueSolution
Large CSS outputCheck for dynamic classes, safelist issues
Slow buildsEnsure v4, check file globs
Missing stylesCheck content detection, class names
Slow animationsUse GPU-accelerated properties
问题解决方案
CSS输出体积过大检查动态类名、安全列表配置问题
构建速度慢确保使用v4版本,检查文件匹配规则
样式缺失检查内容检测配置、类名拼写
动画卡顿使用GPU加速属性

Lazy Loading CSS

CSS懒加载

For very large apps, consider code-splitting CSS:
javascript
// Dynamically import CSS for routes
const AdminPage = lazy(() =>
  import('./admin.css').then(() => import('./AdminPage'))
)
对于超大型应用,可考虑拆分CSS代码:
javascript
// 动态导入路由对应的CSS
const AdminPage = lazy(() =>
  import('./admin.css').then(() => import('./AdminPage'))
)

Best Practices Summary

最佳实践总结

  1. Let JIT do its work - Don't safelist unnecessarily
  2. Use complete class names - Avoid dynamic concatenation
  3. Specific transitions - Not
    transition-all
  4. GPU properties - Prefer
    transform
    and
    opacity
  5. Minimal theme - Only define what you use
  6. Production builds - Always use production mode
  7. Measure - Check your actual CSS size
  1. 让JIT自动处理 - 不要不必要地配置安全列表
  2. 使用完整类名 - 避免动态拼接类名
  3. 使用特定过渡属性 - 不要使用
    transition-all
  4. 优先GPU加速属性 - 优先使用
    transform
    opacity
  5. 精简主题配置 - 仅定义需要的内容
  6. 使用生产环境构建 - 始终启用生产模式
  7. 测量性能 - 检查实际CSS大小