Vue 2 老项目从 webpack 4 迁移到 Vite 4 的实战记录
背景
上周帮一个朋友的 Vue 2 老项目升级构建工具链,原先是 webpack 4,构建一次要三分多钟,改一行代码热更新也要十几秒。趁着周末把整套构建迁到 Vite,顺手记录了完整的迁移过程和踩到的坑,给有同样需求的同学一个可以照着做的路线。
为什么是 Vite
Vue 2 默认的脚手架绑死了 webpack 4,node 17 以上还会报 ERR_OSSL_EVP_UNSUPPORTED 的错,因为新版 OpenSSL 不再支持 webpack 4 用的哈希算法。与其打补丁,不如直接换 Vite。Vite 用 esbuild 做依赖预构建,开发模式按需编译,冷启动基本是秒开。
需要说明的是,Vue 2 用 Vite 要靠 vite-plugin-vue2 这个社区插件,官方的 @vitejs/plugin-vue 只支持 Vue 3。虽然是非官方方案,但生产环境跑了大半年没有出过问题。
迁移步骤
第一步:装依赖
npm i -D vite@4 vite-plugin-vue2
npm i -D @vitejs/plugin-legacy
装 legacy 插件是因为项目还要兼容 Chrome 60 之类的老浏览器,esbuild 默认只输出 ES2015+ 的产物。
第二步:新建 vite.config.js
import { defineConfig } from 'vite'
import vue from 'vite-plugin-vue2'
import legacy from '@vitejs/plugin-legacy'
export default defineConfig({
plugins: [
vue(),
legacy({ targets: ['Chrome >= 58', 'IE >= 11'] })
],
resolve: {
alias: { '@': '/src' }
},
server: {
port: 8080,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
}
})
alias 里的 @ 原来是 webpack 的 resolve.alias 配的,Vite 用 resolve.alias 承接,注意路径前要不要加 / 取决于你原项目怎么引用的。
第三步:处理入口
index.html 要从 public/ 挪到项目根目录,并把引用入口的 script 改成 module:
<script type="module" src="/src/main.js"></script>
原来 webpack 通过 HTMLWebpackPlugin 注入的 <%= %> 模板语法全部删掉。
第四步:环境变量改名
webpack 的 process.env.VUE_APP_xxx 要改成 import.meta.env.VITE_xxx,全局搜索替换即可,.env.production 里的前缀也从 VUE_APP_ 改成 VITE_。
踩到的四个坑
第一,require 语法。 老代码里有不少 require('./assets/logo.png'),esbuild 不认。图片引用统一改成 import logo from '@/assets/logo.png';JSON 文件同理,require('./a.json') 改成 import a from './a.json'。
第二,CommonJS 依赖。 有一个只提供 CJS 的老依赖,开发模式会报 default is not exported。在 optimizeDeps.include 里把它加进去让 esbuild 预构建一次就正常了。
第三,全局挂载的库。 项目里 echarts 是在 main.js 里 Vue.prototype.$echarts = echarts 挂的,迁移时漏了 import echarts from 'echarts',因为原来写在 webpack 的 ProvidePlugin 里。这类隐式注入要挨个排查。
第四,动态路由的懒加载。 () => import(/* webpackChunkName */ '@/views/' + name + '.vue') 这种拼路径的动态导入,Vite 的 glob 导入写法是:
const modules = import.meta.glob('@/views/**/*.vue')
const comp = modules['/src/views/' + name + '.vue']
变量拼路径 Vite 是支持静态分析的,但混合了 webpack 注释就要重写。
迁移结果
| 指标 | webpack 4 | Vite 4 |
|---|---|---|
| 冷启动 | 约 45s | 约 1.2s |
| 热更新 | 10~15s | 300ms 内 |
| 生产构建 | 3min20s | 52s |
| 产物体积 | 4.1MB | 3.7MB |
产物变小的原因主要是 legacy 插件把 polyfill 拆成了按浏览器加载的两份,现代浏览器只下载轻的那份。
小结
整个迁移花了一个下午加一个晚上,其中一大半时间耗在排查 require 和动态导入上。如果项目本身就是 Vue 3 + 新脚手架,迁移成本会低很多。建议先在新分支上做,用 Vite 的 dev server 和原 webpack 的 dev server 并行跑几天,逐页对比再切流量。
- 点赞
- 收藏
- 关注作者
评论(0)