前言
目前一个用webpack构建的vue2.X 项目由于业务扩展越来越大,导致项目在本地编译时热更新很慢,页面更新需要10几秒以上。为提高团体开发速度和效率,最近打算把底部打包构建的环境由webpack迁移为vite。
兼容性注意
Vite 需要 Node.js 版本 >= 12.0.0。
为什么 Vite 启动这么快
底层实现上, Vite 是基于 esbuild 预构建依赖的
esbuild 使用 go 编写,并且比以 js 编写的打包器预构建依赖, 快 10 - 100 倍。 因为 js 跟 go 相比实在是太慢了,js 的一般操作都是毫秒计,go 则是纳秒
两者的启动方式也有所差异
webpack启动方式:
Webpack 会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
vite启动方式:
Vite 是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。
webpack如何升级为vite
vue3.x中webpack迁移vite,主要借助wp2vite脚手架,改造过程中也会遇到很多问题,可参考这篇博文 项目 Webpack 转 Vite 实战
vue2.x中webpack转vite, 主要借助 vite-plugin-vue2插件,具体可参考 Vue2老项目使用vite2升级
改造流程
- 安装相关包
npm install vite -D
npm install @vue/compiler-sfc -D
npm install vite-plugin-vue2 -D - 新建vite.config.js, 文件内容见附录1
- 给index.html增加main.js入口
<script type="module" src="/src/main.js"></script>
项目改造中遇到的坑
除上述博文提及的坑之外,还遇到了一些其它的问题,总结如下:
-
文件后缀省略导致页面报错404(例:vue文件引入时,webpack只需要文件名),在vite.config.js配置resolve.extensions中添加对应后缀,vite默认有[’.mjs’, ‘.js’, ‘.ts’, ‘.jsx’, ‘.tsx’, ‘.json’]
-
入口文件不是index.html,或者不在根目录,导致资源报错404;需将 /public/index.html 挪出到根目录路径下, 或者改变vite.config.js 默认的入口路径地址。
-
@别名的使用,修改相对路径地址
-
sass语言的扩展,默认生成的vite配置文件,只支持less语言,如项目中涉及sass语言,需额外扩展引入
-
webpack中使用require引入文件, 但vite中需要改成 important 引入;
因为vite的底层有使用到Rollup组件打包,但Rollup不支持common.js语法风格,所以需要改成esModule语法才能正确编译;
vite.config.js 中 optimizeDeps 也是此原理;目前社区中大部分模块都没有设置默认导出 esm,而是导出了 cjs 的包,目前在 vite 项目里直接使用 lodash 之类的包会报错;
optimize 命令专门为解决模块引用的坑而开发;将原来common.js语法转译为esm风格的语法供vite使用
...
optimizeDeps: {
// @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly
include: [
'@iconify/iconify',
'ant-design-vue/es/locale/zh_CN',
'moment/dist/locale/zh-cn',
'ant-design-vue/es/locale/en_US',
'moment/dist/locale/eu',
],
exclude: ['vue-demi'],
},
...
- svg字体图标的批量导入变更:
webpack环境下,利用require.context批量导出
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
vite环境下,transformIndexHtml钩子函数读取到html源文件,并将svg标签插入到html的body中
核心代码如下:
import {
readFileSync, readdirSync } from 'fs'
// id 前缀
let idPerfix = ''
// 识别svg标签的属性
const svgTitle =