近年来 Vite 因启动快、HMR 更及时、配置更轻而被大量项目采用。如果你现在用的是 Vue CLI(基于 webpack),想迁移到 Vite,本文按步骤、并附常见问题与示例配置,帮助你平滑迁移。
目录
迁移前准备
迁移步骤(逐步操作)
常见配置映射与示例(vite.config.ts)
常见问题与排查
进阶:测试、CI、兼容旧浏览器
迁移清单(Checklist)
1. 迁移前准备
确认 Vue 版本
Vue 3:推荐直接迁移到 Vite(官方支持 @vitejs/plugin-vue)。
Vue 2:可以用 community 插件(vite-plugin-vue2 / @vitejs/plugin-vue2),但生态兼容性可能不如 Vue 3 顺畅,建议评估是否升级到 Vue 3。
备份/新分支:在新分支上操作,保证回退方便。
升级依赖:先将项目依赖升级到兼容的最新版本(vue-router、vuex/Pinia 等)。
清理无用依赖:减少迁移时的问题来源。
2. 迁移步骤(逐步操作)
下面以 Vue 3 + TypeScript 项目为例,演示迁移流程。
安装 Vite 与必要插件
# 安装 vite 及官方 Vue 插件
npm install -D vite @vitejs/plugin-vue
# 如果使用 TypeScript / 类型检查
npm install -D vite-plugin-checker
# 推荐:使用 vite 的快速刷新/兼容 React 的同类项目不需要此项
新增启动脚本(修改 package.json)
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
// 保留原来的 test/lint 等脚本
}
迁移入口文件和 index.html
Vue CLI:通常入口为 src/main.js 并在 public/index.html 注入构建结果。
Vite:使用基于模块的 index.html(位于项目根),并直接作为入口加载脚本。
示例:把 public/index.html 转为 Vite 的 index.html(放在项目根)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>My App</title>
<!-- Vite 会注入 script -->
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
注意:
使用 type="module" 并写绝对路径 /src/main.ts(开发时 Vite 直接解析)。
public 目录仍可保留,Vite 会在构建时把它静态复制到 dist。
调整入口代码(main.ts / main.js)
通常不需要太多修改,但注意:
process.env.NODE_ENV -> import.meta.env.MODE
process.env.VUE_APP_... -> import.meta.env.VITE_...
示例:
// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
转换环境变量
Vue CLI 中以 VUE_APP_ 开头的变量,在 Vite 中需改为 VITE_ 前缀。
.env 文件示例:
VITE_API_BASE=/api
VITE_SOME_KEY=xxx
在代码中访问:import.meta.env.VITE_API_BASE
处理别名(@)与路径解析
在 vite.config.ts 中配置别名(推荐使用绝对路径解析):
示例 vite.config.ts 中的 alias(见下一节完整示例)。
替换/移除 webpack 特有配置
vue.config.js 中的 configureWebpack、chainWebpack、devServer 等需要迁移到 vite.config.ts:
devServer.proxy -> server.proxy
alias -> resolve.alias
publicPath / assetsDir -> build.base / build.assetsDir
loader(file-loader / url-loader / raw-loader 等):
Vite 内置对静态资源的处理(通过 import 引入,基于文件大小自动内联或产生文件)。
若原项目使用特殊 loader(如 svg-sprite-loader、svg-inline-loader 或 custom loaders),需要寻找 Vite 插件替代(例如 vite-plugin-svg-icons、vite-plugin-svgr 等)。
处理 CSS / 预处理器
全局 scss 变量(Vue CLI 通常在 vue.config.js 配置)
Vite 可用 css.preprocessorOptions.sass/scss 来注入全局变量或 mixin。
示例:
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
}
处理第三方依赖的 CommonJS 问题
Vite 使用原生 ESM,第三方包若是 CommonJS,可能需在 optimizeDeps.include 中预构建,或在 build.rollupOptions.external 中做处理。
运行 & 修复错误
npm run dev
按照终端与浏览器控制台报错逐步修复常见问题(路径、环境变量、依赖 ESM 等)。
3. 常见配置映射与示例配置(vite.config.ts)
下面给出一个比较完整的 Vue 3 + TypeScript 项目 vite.config.ts 示例,涵盖 alias、proxy、全局 scss、插件与依赖优化。
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import checker from 'vite-plugin-checker'
export default defineConfig(({ command, mode }) => {
return {
plugins: [
vue(),
checker({ typescript: true }) // 在dev时做类型检查
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, '')
}
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
},
optimizeDeps: {
include: ['some-cjs-lib'], // 若有需要预构建的依赖
exclude: ['large-only-esm-lib']
},
build: {
outDir: 'dist',
assetsInlineLimit: 4096,
rollupOptions: {
// 根据需要自定义打包分包策略
}
}
}
})
说明关键点:
alias:把 '@' 指向 src,和 Vue CLI 常用 alias 行为一致。
server.proxy:开发代理(等价于 vue.config.js devServer.proxy)。
css.preprocessorOptions.additionalData:注入全局 scss 变量。
optimizeDeps:解决 require is not defined / CommonJS 问题。
4. 常见问题与排查
HMR 无效或页面不刷新
检查是否有反向代理(NGINX、Docker)阻断 WebSocket。
检查项目中使用的第三方依赖是否破坏 ESM(需要 optimizeDeps.include)。
“require is not defined” / “exports is not defined”
说明某个包仍是 CommonJS。解决方法:
在 vite.config.ts 的 optimizeDeps.include 中预构建;
或在源码中使用动态 import 替代 require;
或寻找 ESM 版本的包。
环境变量无法读取
Vite 只注入以 VITE_ 开头的变量,需把 .env 中变量前缀改为 VITE_,代码中用 import.meta.env 访问。
图片/静态资源路径问题
Vite 中在 index.html 或 css 使用绝对路径时以 / 开头指向项目根。public 目录内的文件可直接通过 /file.ext 访问。
构建时可通过 build.base 设置静态资源基本路径(等价于 Vue CLI 的 publicPath)。
类型检查不生效
Vite 默认不会做完整的 TypeScript 类型检查,推荐用 vite-plugin-checker 或在 CI 中运行 tsc --noEmit。
5. 进阶:测试、Lint、兼容旧浏览器
单元测试(Jest -> Vitest)
推荐使用 Vitest(与 Vite 深度集成,启动快、与测试环境兼容)。
也可继续使用 Jest,但需额外配置以支持 ESM 与 Vite 的别名等。
安装 Vitest 示例:
npm install -D vitest @vitejs/plugin-vue @testing-library/vue
# package.json
"test": "vitest"
E2E 测试(Cypress / Playwright)
大多数工具与 Vite 无冲突,只需确保 CI 能构建静态站点或启动 dev server。
兼容旧浏览器
如果需要支持 IE11/旧浏览器,可使用 @vitejs/plugin-legacy 插件,但会显著增加构建体积与时间。
推荐评估是否真的需要兼容老浏览器,或在需要兼容的业务线单独处理。
6. 迁移清单(Checklist)
在新分支中操作并备份
安装 vite 与 @vitejs/plugin-vue(或 vue2 插件)
添加 npm 脚本(dev/build/preview)
将 public/index.html 转为根目录下的 index.html,引用 /src/main.*
修改 main.ts/js(移除对 process.env 的直接依赖)
把 VUE_APP_* 环境变量改为 VITE_*
迁移别名(@)到 vite.config.ts
将 vue.config.js 中的 proxy、css、publicPath 等迁移到 vite.config.ts 的对应字段
处理 webpack 特有 loader(查找 Vite 插件替代)
处理 CommonJS 依赖(optimizeDeps.include)
配置全局 scss(css.preprocessorOptions)
添加类型检查插件(vite-plugin-checker)或在 CI 中运行 tsc
运行开发服务器并修复报错
做一次生产构建(vite build)并测试 dist 文件
更新 CI/CD 脚本(用 vite build 替代 vue-cli-service build)
迁移/评估测试(Jest -> Vitest)
7. 小结与建议
迁移到 Vite 最常见的问题是第三方依赖的 CommonJS 兼容与 webpack 特有 loader 的替换。通过 optimizeDeps、寻找 Vite 插件或在代码中替换(动态 import / 使用 ESM 版本)通常可以解决。
先在新分支逐步迁移与验证(dev、build、E2E),确保 CI/部署链路也跟着更新。
如果项目仍使用 Vue 2,权衡是先迁移到 Vite(使用兼容插件)还是先升级到 Vue 3 再迁移。通常升级到 Vue 3 更能长期受益,但需要更多工作量。