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

📌 迁移背景

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

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

🔍 迁移准备

  1. 了解 Tailwind CSS v4 新特性

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

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

    bash

    sql 复制代码
    pnpm install tailwindcss@4 @tailwindcss/postcss autoprefixer --save-dev

🛠️ 迁移过程

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

bash

perl 复制代码
# 卸载 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

    arduino 复制代码
    // 删除以下导入
    import 'virtual:windi.css'
    import 'virtual:windi-devtools'

2. 配置文件迁移

windi.config.tstailwind.config.js

javascript

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

less 复制代码
@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

arduino 复制代码
import '@/styles/tailwind.css';

4. PostCSS 配置更新

javascript

yaml 复制代码
// 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

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

3. 暗黑模式切换异常

解决方案

javascript

java 复制代码
// 确保配置了 darkMode: 'class'
module.exports = {
  darkMode: 'class',
  // ...
}

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

4. 依赖冲突问题

解决方案

bash

bash 复制代码
# 清除 node_modules 和 lock 文件
rm -rf node_modules
rm pnpm-lock.yaml

# 重新安装依赖
pnpm install
相关推荐
赖龙6 小时前
pnpm vs npm
前端·npm·node.js
学如逆水,不进则退7 小时前
在线免费音频剪辑:NBTools 可视化波形裁剪 MP3/WAV,本地处理免上传
前端·音视频
Mh7 小时前
虚拟滚动真的比普通滚动性能更好吗?
前端·javascript·性能优化
pe7er7 小时前
React + Ant Design 中的 IME (输入法合成)安全输入组件
前端
Super 含8 小时前
Android 启动优化(二):TTID、TTFD 与 Macrobenchmark 启动性能测量
前端
Python私教8 小时前
别急着加 llms.txt:企业官网面向 AI 搜索的工程清单
前端·人工智能·seo
东方小月8 小时前
从零开发一个 Coding Agent(十三):实现安全的 read 文件读取工具
前端·人工智能·全栈
东方小月9 小时前
从零开发一个 Coding Agent(十二):实现版本化 JSONL 与真实 CLI 入口
前端·设计模式·前端框架
FL162386312910 小时前
室内易燃物识别易燃评估室内易燃程度识别分割数据集labelme格式1015张85类别
java·服务器·前端
用户0595401744610 小时前
把 AI 长期记忆去重测试从 20 分钟压到 40 秒,重复率从 18% 干到 1.5%
前端·css