🚀 从 Windi CSS 迁移到 Tailwind CSS v4 完整实践指南

296 阅读2分钟

📌 迁移背景

  • Windi CSS 已停止维护(最后更新于 2022 年),存在稳定性与兼容性风险
  • Tailwind CSS 作为行业标准,提供长期支持、活跃生态及更完善的工具链

重要提示:迁移前请务必备份整个项目!

🔍 迁移准备

  1. 了解 Tailwind CSS v4 新特性

    • 增强的 JIT 引擎性能
    • 改进的暗黑模式支持
    • 全新的 @reference 指令
    • 更智能的类名推导机制
  2. 备份关键文件

    • windi.config.ts
    • postcss.config.js
    • 所有包含 Windi CSS 导入的文件
  3. 准备安装包

    bash

    pnpm install tailwindcss@4 @tailwindcss/postcss autoprefixer --save-dev
    

🛠️ 迁移过程

1. 替换依赖与清理旧配置

bash

# 卸载 Windi CSS
pnpm remove windicss vite-plugin-windicss windicss-analysis

# 安装 Tailwind CSS v4
pnpm install tailwindcss@4 @tailwindcss/postcss autoprefixer --save-dev

清理工作

  1. 删除 @/plugins/windi.css 文件

  2. 移除所有 Windi CSS 导入语句:

    javascript

    // 删除以下导入
    import 'virtual:windi.css'
    import 'virtual:windi-devtools'
    

2. 配置文件迁移

从 windi.config.ts 到 tailwind.config.js

javascript

// 根目录创建 tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: 'class',
  content: ['./src/**/*.{vue,html,jsx,tsx}'],
  theme: {
    extend: {
      backgroundColor: {
        'v-dark': 'var(--dark-bg-color)',
      },
    },
  },
  plugins: [
    function({ addComponents }) {
      const range = (size, startAt = 1) => 
        Array.from(Array(size).keys()).map(i => i + startAt);
      
      const obj = {};
      range(50).forEach(i => {
        obj[`.border-top-${i}`] = { borderTopWidth: `${i}px` };
        obj[`.border-left-${i}`] = { borderLeftWidth: `${i}px` };
        obj[`.border-right-${i}`] = { borderRightWidth: `${i}px` };
        obj[`.border-bottom-${i}`] = { borderBottomWidth: `${i}px` };
      });
      
      addComponents({
        '.hover-trigger': {
          display: 'flex',
          height: '100%',
          padding: '1px 10px 0',
          cursor: 'pointer',
          alignItems: 'center',
          transition: 'background var(--transition-time-02)',
          '&:hover': {
            backgroundColor: 'var(--top-header-hover-color)',
          },
        },
        '.dark .hover-trigger:hover': {
          backgroundColor: 'var(--el-bg-color-overlay)',
        },
        ...obj
      });
    },
  ],
}

3. 样式文件迁移

创建 src/styles/tailwind.css

css

@tailwind base;
@reference "tailwindcss"; /* Tailwind v4 核心指令 */
@tailwind components;
@tailwind utilities;

/* 自定义工具类 */
.hover-trigger {
  @apply flex h-full px-[10px] pt-1 cursor-pointer items-center 
         transition-[background] duration-[var(--transition-time-02)];
}

.hover-trigger:hover {
  @apply bg-[var(--top-header-hover-color)];
}

.dark .hover-trigger:hover {
  @apply bg-[var(--el-bg-color-overlay)];
}

/* 边框工具类 (示例) */
.border-top-1 { border-top-width: 1px; }
.border-left-1 { border-left-width: 1px; }
/* ...扩展到需要的尺寸 */

在 main.ts 中引入

typescript

import '@/styles/tailwind.css';

4. PostCSS 配置更新

javascript

// postcss.config.js
module.exports = {
  plugins: {
    '@tailwindcss/postcss': {
      config: './tailwind.config.js'
    },
    autoprefixer: {},
    'postcss-px-to-viewport': {
      viewportWidth: 1920,
      unitPrecision: 5,
      viewportUnit: 'vw',
      selectorBlackList: [],
      minPixelValue: 1,
      mediaQuery: false
    }
  }
}

⚠️ 迁移常见问题及解决方案

1. 工具类识别问题

现象:迁移后 Tailwind 无法识别 pt-1 等工具类
解决方案

  1. 确保 tailwind.css 中包含 @reference "tailwindcss";
  2. 检查 content 配置是否覆盖所有文件路径
  3. 重启开发服务器清除缓存

2. 自定义工具类不生效

解决方案

javascript

// 在 tailwind.config.js 中正确使用 addComponents
plugins: [
  function({ addComponents }) {
    addComponents({
      '.my-class': {
        padding: '2rem',
        '&:hover': {
          color: '#fff'
        }
      }
    })
  }
]

3. 暗黑模式切换异常

解决方案

javascript

// 确保配置了 darkMode: 'class'
module.exports = {
  darkMode: 'class',
  // ...
}

// 在HTML根元素切换类名
document.documentElement.classList.toggle('dark');

4. 依赖冲突问题

解决方案

bash

# 清除 node_modules 和 lock 文件
rm -rf node_modules
rm pnpm-lock.yaml

# 重新安装依赖
pnpm install