Skip to content

Vite 迁移指南

🚀 迁移目标:从 Vue CLI / Webpack 迁移至 Vite,大幅提升开发体验和构建速度

📦 核心插件

Vite 插件

代码规范工具

📚 迁移参考案例

以下项目已完成 Vite 迁移,可作为参考:

项目类型链接
demo-uiCommitc376f84
playlet-uiPR#77
playlet-supply-web-uiPR#2

🔧 迁移步骤

1️⃣ 更新 package.json

基础信息调整

json
{
  "name": "ruoyi",
  "type": "module",  // ← 启用 ES Module
  "version": "3.2.0",
  "description": "模板项目",
  "author": "wudi",
  "engines": {
    "node": ">=18.20.3"  // ← 要求 Node.js 18+
  }
}

脚本命令迁移

json
{
  "scripts": {
    // ❌ 移除 Vue CLI 命令
    "dev": "vue-cli-service serve",
    "test": "vue-cli-service build --mode test",
    "build:prod": "vue-cli-service build",
    "lint": "eslint --ext .js,.vue src",
    
    // ✅ 使用 Vite 命令
    "dev": "vite",
    "test": "vite build --mode test",
    "build:prod": "vite build",
    "preview": "vite preview --port 8889",
    
    // ✅ 增强代码质量工具
    "lint": "eslint ./src/**/*.{vue,js}",
    "lint:fix": "eslint ./src/**/*.{vue,js} --fix",
    "format": "prettier --check \"./src/**/*.{vue,js}\"",
    "format:fail": "prettier --check --write \"./src/**/*.{vue,js}\""
  }
}

依赖包清理与升级

json
{
  "dependencies": {
    "@mgcloud/lib-base": "1.1.0",
    "@mgcloud/pc-base-ui": "0.0.10",
    "@vueuse/core": "10.10.0",
    "axios": "0.24.0",
    "core-js": "3.25.3",
    "echarts": "5.5.0",
    "element-ui": "2.15.14",
    "moment": "2.29.1",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "number-precision": "1.6.0",
    "path-to-regexp": "2.4.0",
    "sortablejs": "1.10.2",
    "vue": "2.7.16",
    "vue-router": "3.6.5",
    "vuex": "3.6.2"
  },
  "devDependencies": {
    // ❌ 移除 Vue CLI 相关依赖
    "@vue/cli-plugin-babel": "4.4.4",
    "@vue/cli-plugin-eslint": "4.4.4",
    "@vue/cli-plugin-unit-jest": "4.4.4",
    "@vue/cli-service": "4.4.4",
    "autoprefixer": "9.5.1",
    "babel-eslint": "10.1.0",
    "babel-jest": "^26.6.1",
    "babel-plugin-dynamic-import-node": "2.3.3",
    "html-webpack-plugin": "3.2.0",
    "husky": "1.3.1",
    "lint-staged": "8.1.5",
    "script-ext-html-webpack-plugin": "2.1.3",
    "script-loader": "0.7.2",
    "svg-sprite-loader": "4.1.3",
    "vue-template-compiler": "2.6.14",
    
    // ❌ 移除旧版本工具
    "eslint": "6.7.2",
    "eslint-plugin-vue": "6.2.2",
    "sass": "1.27.0",
    "sass-loader": "^10.1.1",
    
    // ✅ 添加 Vite 生态依赖
    "@vitejs/plugin-vue2": "2.3.1",
    "@vitejs/plugin-vue2-jsx": "1.1.1",
    "vite": "5.2.11",
    "vite-plugin-svg-icons": "2.0.1",
    
    // ✅ 添加代码规范工具
    "@cdlab996/eslint-config-vue2": "0.0.13",
    "@cdlab996/prettier-config": "0.0.13",
    "eslint": "8.57.0",
    "prettier": "3.3.1",
    
    // ✅ 添加辅助工具
    "@unocss/eslint-plugin": "0.60.3",
    "unocss": "0.60.3",
    "fast-glob": "3.3.2",
    "rollup-plugin-visualizer": "5.12.0",
    "sass": "1.32.13"
  }
}

2️⃣ 创建 Vite 配置文件

在项目根目录创建 vite.config.js

javascript
import path from 'node:path'
import { writeFileSync } from 'node:fs'
import process from 'node:process'
import { defineConfig, loadEnv } from 'vite'
import createVitePlugins from './vite/plugins'
import { name, version } from './package.json'

console.warn('project info:')
console.warn(`${name} version: ${version}, environment: ${process.env.NODE_ENV}`)

// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
  const { VITE_APP_ENV } = env
  const isProduction = VITE_APP_ENV === 'production' || VITE_APP_ENV === 'test'

  if (isProduction) {
    // 生成版本号文件
    const filePath = path.resolve(__dirname, 'public', 'manifest.json')
    writeFileSync(filePath, JSON.stringify({ timestamp: new Date().getTime() }))
  }

  return {
    base: VITE_APP_ENV === 'production' ? '/' : '/',
    build: {
      outDir: 'dist',
      assetsDir: 'static',
      // rollupOptions: {
      //   output: {
      //     entryFileNames: 'static/js/[name].[hash].js',
      //     chunkFileNames: 'static/js/[name].[hash].js',
      //     manualChunks(id) {
      //       if (id.includes('node_modules')) {
      //         if (id.includes('element-ui')) {
      //           return 'chunk-elementUI'
      //         }
      //         return 'chunk-libs'
      //       }
      //       if (id.includes(path.resolve(__dirname, 'src/components'))) {
      //         return 'chunk-commons'
      //       }
      //     },
      //   },
      // },
    },
    plugins: createVitePlugins(env, command === 'build'),
    resolve: {
      alias: {
        vue: 'vue/dist/vue.esm.js',
        '@': path.resolve(__dirname, './src'),
      },
      // https://cn.vitejs.dev/config/#resolve-extensions
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    },
    server: {
      port: env.VITE_APP_PORT,
      host: true,
      // open: true,
      // proxy: {
      //   // https://cn.vitejs.dev/config/#server-proxy
      //   '/dev-api': {
      //     target: 'http://localhost:8080',
      //     changeOrigin: true,
      //     rewrite: (p) => p.replace(/^\/dev-api/, '')
      //   }
      // }
    },
    // fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
    css: {
      postcss: {
        plugins: [
          {
            postcssPlugin: 'internal:charset-removal',
            AtRule: {
              charset: (atRule) => {
                if (atRule.name === 'charset') {
                  atRule.remove()
                }
              },
            },
          },
        ],
      },
    },
  }
})

3️⃣ 创建 ESLint 配置

创建 .eslintrc.cjs

javascript
module.exports = {
  extends: '@cdlab996/eslint-config-vue2',
}

4️⃣ 创建 Prettier 配置

创建 .prettierrc.cjs

javascript
module.exports = {
  ...require('@cdlab996/prettier-config'),
  // Add your custom configurations here
}

5️⃣ 更新入口 HTML

public/index.html 移至项目根目录,并更新:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>项目名称</title>
</head>
<body>
  <div id="app"></div>
  <!-- ✅ Vite 入口 -->
  <script type="module" src="/src/main.js"></script>
</body>
</html>

6️⃣ 调整环境变量

.env.* 文件中的环境变量前缀从 VUE_APP_ 改为 VITE_

bash
# .env.production
# ❌ 旧前缀
VUE_APP_BASE_API=https://api.example.com

# ✅ 新前缀
VITE_APP_BASE_API=https://api.example.com

在代码中访问环境变量:

javascript
// ❌ 旧方式
const apiUrl = process.env.VUE_APP_BASE_API

// ✅ 新方式
const apiUrl = import.meta.env.VITE_APP_BASE_API

7️⃣ 更新静态资源引用

javascript
// ❌ 旧方式(require)
const logo = require('@/assets/logo.png')

// ✅ 新方式(import 或 new URL)
import logo from '@/assets/logo.png'
// 或
const logo = new URL('@/assets/logo.png', import.meta.url).href

8️⃣ 移除 Webpack 特定代码

删除或替换以下 Webpack 特定代码:

javascript
// ❌ 移除 require.context
const requireComponent = require.context('./components', false, /\.vue$/)

// ✅ 使用 import.meta.glob
const modules = import.meta.glob('./components/*.vue')

✅ 迁移检查清单

  • [ ] 已更新 package.json 配置
  • [ ] 已创建 vite.config.js
  • [ ] 已配置 ESLint 和 Prettier
  • [ ] 已更新入口 HTML 文件
  • [ ] 环境变量前缀已改为 VITE_
  • [ ] 静态资源引用已更新
  • [ ] 已移除 Webpack 特定代码
  • [ ] 开发服务器启动正常
  • [ ] 生产构建成功
  • [ ] 功能测试通过

🎯 迁移收益

对比项Vue CLI (Webpack)Vite
冷启动30-60s2-5s
热更新3-5s<1s
生产构建2-5min1-3min
开发体验⭐⭐⭐⭐⭐⭐⭐⭐

📚 参考资源

⚠️ 常见问题

Q: Node.js 版本要求?

A: 建议使用 Node.js 18.20.3 或更高版本

Q: 是否支持 IE 11?

A: Vite 不支持 IE 11,需要现代浏览器

Q: 如何调试构建产物?

A: 使用 rollup-plugin-visualizer 分析打包体积:

bash
npm run build:prod
# 构建完成后会生成 stats.html 可视化报告