从0到1将一个Vue3.0+Vant-UI(v3.x)项目从Vue-cli迁移到Vite

你可能想知道

关于前端构建一些知识提纲
为什么选Vite?-官方

相关工具

wp2vite,一个将webpack项目转换为vite项目的工具


对比

参考来自 Vue-cli 与 Vite的区别-2021/2/22

对比 Vue-cli Vite
生态&社区 生态完善,历经检验 ✅ 后起之秀,根基不深
- 问题&解决方案多✅ 目前社区支持不够丰富
- 插件丰富✅ 目前插件不够丰富
- - -
兼容 兼容Vue2✅ 对Vue3兼容较好,Vue2可能会有问题
- 兼容部分旧版浏览器✅ 开发环境仅支持现代浏览器(ES6),生产可以根据配置
- 兼容CommonJS ✅ 不兼容CommonJS
- - -
开发&构建 开发和生产构建方式一致(基于webpack)✅ 开发和生产构建不一致(开发基于ESM,生产构建基于Rollup)
- 开发启动速度慢,HMR全量更新,响应较慢 开发启动速度一般,HMR按需更新,响应极快✅
- 开发生成将随着项目内容线性增长,时间复杂度O(n) 开发生成时间复杂度始终为O(1) ✅
- 基于webpack打包,打包后内容体积偏大 对比来说,打包基于Rollup,如使用 tree shake 打包后内容体积可适当缩小✅


迁移方案

  1. 使用 vite 创建一个新的项目,将项目文件逐步迁移过去
  2. 创建新分支,直接在新分支的文件上着手 本次迁移采用该方案

迁移过程

  • 安装Vite请参考官方文档
  • 新增vite.config.js配置文件并将vue.config.js配置迁移 [可使用wp2vite工具操作]
  • 修改package.json,删除不必要的包和新增vite所需包
    • 删除所有vue-cli的包
    • 删除webpack相关的包
    • 修改package.json中scripts命令映射
  • 修改env配置文件使其符合Vite规范 文档说明
  • 删除package-lock.json文件和node_modules文件夹
  • 重新执行 npm install
  • 执行 vite 生成命令 vite  查看是否正常执行
  • 执行 vite 构建命令 vite build 查看是否正常构建
  • 构建正常后,执行 vite 本地构建测试命令 vite preview 查看本地构建运行结果是否正常
  • 以上均正常,迁移成功

前后对比

对比环境采用相同用户在Chrome浏览器无缓存状态下的数据
机器环境:Mac os
Chrome版本:V93.0.4577.63
NodeJS: v16.9.1

对比 Vue-cli Vite 备注
开发环境 - - -
服务启动时长 25000ms±10000ms 700ms±100ms 速度提升20~35倍
HMR(热更新)时间 800±100ms 20ms± 几乎保存即生效
首次页面请求数(All) 17 412 Vite开发环境不打包直接import依赖,会导致页面请求内容较多,如css多级依赖
请求内容Size 7MB 5.6MB Vite 开发按需加载,无打包,内容较少
总耗时 1.98ms 1.92ms 总耗时会有闪动,基本持平
生产环境(模式es2015) - - -
产物大小 6MB 2.9MB 包大小减少50%
首次页面请求数(All) 19 16
页面内容Size 1.3MB 581K 页面内容减少60%
首次打开页面时间 5.04s 725ms 首次页面打开时间提升7倍

值得注意

  • Vite 构建使用ESM,不支持CommonJS语法

所以需要将引用包方式从const r = require('package_name') 修改为 import pageage from 'package_name'

  • 入口文件可配置,默认路径由/public 改为 / 官方说明

Vue-cli 入口文件为 ~/public 但是 Vite的路径可在 vite.config.js 中配置root属性,默认为 process.cwd()。所以需要将原/public下的文件迁移到/根目录,或者roo改为/public

  • 环境变量使用变更,从 process.env 换成 import.meta.env

在一些js中可能会使用到环境变量进行判断,如process.env.NODE_ENV 在Vite中需要修改为 import.meta.env.MODE ,在index.html入口文件中,如果使用了ejs语法,此时无法通过import.meta.env拿到环境变量。详见下方坑&填坑/②

  • 对CDN支持不友好,建议使用 npm 安装后 import 引入

在迁移时遇到问题,在使用cdn时, 组件无法正常工作,报错 TypeError: ParentNode is undefined ,改为 import 后正常。
涉及到 vuevuexvue-router


坑&填坑

最下方有一些好心网友经验文档,建议按需查阅

  • ① index.html中ejs代码段未工作

vue-cli默认使用html-webpack-plugin解释/public/index.html中的ejs模板语法,且开箱即用不需要自行再引入该包。vue-cli静态html说明
vite需要支持入口文件中的ejs语法,需要在vite.config.js配置文件中引入插件vite-plugin-html来进行工作 。

  • ② index.html中的process.envimport.meta.env无法正常工作

1.Vite环境变量暴露变更,由process.env更改为import.meta.env
2.Vite 不支持index.html文件中使用import.meta.env
3.需要通过在vite.config.js中使用define配置,注入常量。官方文档
4.Vite 暴露的环境变量需要符合envPrefix前缀,注意配置,默认为VITE_

1
* Vite使用define注入env示意代码

// 为保证导入正确,请务必注意配置中和loadEnv()入参中的envDir和 envPrefix保持一致
import { defineConfig, loadEnv } from ‘vite’
export default defineConfig(mode=>{
const envDir = ‘env’
const envPrefix = ‘VITE_’
const env = loadEnv(mode,envDir,envPrefix)
return {
define:{env},
envDir,
envPrefix
}
})

1
2
3
4
5
6
7
```

- ③  path配置 import 等路径别名,如@

> 和vue-cli中使用webpack的resolve.alias一样,vite也使用相同的方式用于路径别名设置。配置方式如下


1
2
3
4
5
resolve:{
alias:{
"@":path.resolve(__dirname,"./src")
}
}
1
2
3
4
5
6

- ④ jsonwebtoken包在运行和构建时有异常错误

> 1.报错 property process is  undefined。<br />原因在jsonwebtoken中有判断process.version Nodejs版本,但是在运行时,已经没有了process环境变量。<br />2.报错 package emitter is not found .<br />原因未知


解决方案:

原来是全量引入jsonwebtoken,但是项目中仅仅使用了jsonwebtoken的decode方法
删除引用jsonwebtoken改为引用jwt-decode,且将对应调用方式调整

1
2
3
4
5
6

- ⑤ svg图生成icon组件,require is undefined

> 之前通过reqire.context(path,true,patter)动态引入全部svg现在只需要通过`vite-plugin-svg-icons`即可


// 原引入方式
import SvgComponent from ‘/path’
import Vue from ‘vue’
export default {
Vue.component(SvgComponent);

const requireAll = reqContext =>reqContext.keys().map(requireContext);
const req = request.context(‘./assets/svg’,true,/.svg$/);
requireAlll(req);

1
2
3
4
5
6

- ⑥ 文件缺失后缀导致import报错

> 原vue-cli默认支持忽略后缀`.vue`,而Vite要求vue文件引入时确定后缀名。但是可以通过配置模糊匹配后缀。[文档](https://cn.vitejs.dev/config/#resolve-extensions)


1
2
3
resolve:{
extensions:['.vue','.js']
}

- ⑦ Vite内联插件报错

> 需要引入插件 `@vitejs/plugin-vue` [Vite插件](https://cn.vitejs.dev/plugins/)


- ⑧ 部分样式异常

> 1.在less,使用了这样的 url('~@/path') 语法,搜索替换 将 ~@ 替换为 @ 就可以了<br />2.前端组件引用vantUI(v3.x)组件库,该组件库按需使用需要引用[vite-plugin-style-import插件](https://github.com/anncwb/vite-plugin-style-import),可参考[vant官方文档#方式二. 在 Vite 项目中按需引入组件](https://vant-contrib.gitee.io/vant/v3/#/zh-CN/quickstart)


---

#### 其他人踩过的坑 🐶

-  👍👍👍  Vue2 项目从 vue-cli(webpack)迁移到了 vite  [前往](https://segmentfault.com/a/1190000039801848) 
-  👍👍 vue-cli迁移vite2实践小结 [前往](https://blog.csdn.net/bbsyi/article/details/114299352) OR [知乎链接](https://zhuanlan.zhihu.com/p/353601634) 
-  👍老项目 Webpack 迁移到 Vite,包含基础知识点和报错解决 [前往](https://blog.csdn.net/weixin_43254766/article/details/116247687) 
-  老的React+webpack项目迁移到vite [前往](https://juejin.cn/post/6989477897505341453) 
-  使用vue-plugin插件钩子对旧代码进行编译前的转换 [前往](https://learnku.com/articles/56423)