记一次webpack转vite踩坑之路
背景
公司的h5项目越来越大,打包进度展示2万+模块, 尽管从webpack2升级到webpack4,冷启动仍需三分多钟,热更新10s左右,占用电脑内存也大,开发体验较差;查阅了很多资料,决定在运行项目时使用vite,提高效率。
冷启动数据 热更新数据
工具
使用的辅助工具为webpack-to-vite originjs.org/guide/tools…
过程
1,安装并运行命令
$ npm install @originjs/webpack-to-vite -g
$ webpack-to-vite <project path>
运行完命令,会在与项目平行的目录copy出一份代码,并可以看到目录下更改了三个文件,conversion.log,index.html(引入vite的main.js),vite.config.js(vite运行配置文件),package.json(引入vite相关包与命令)。
2,package.json引入了新包,重新删除node_modules, install一下并运行
3,发现一些包报node版本警告和报错,这个报错查了一下也是node版本问题,经过多次查资料和调试,将node版本升到16.8.0
4,node-sass报错
node-sass报错,node-sass 已经弃用了 直接安装sass 即可正常使用
5,运行成功,但是报了很多没安装的文件报错
原因是在webpack里配置了很多alias,在vite里面拿不到,将webpack里面的alias和externals(vite-plugin-externals)在vite里面也配置一下,重新运行
6,配置后运行起来后报错global is not defined
index.js?v=7841fec2:23 Uncaught ReferenceError: global is not defined
at <stdin> (index.js?v=7841fec2:23:35)
at __require (index.js?v=7841fec2:3:50)
at index.js?v=7841fec2:1479:16
这个查了好久,我window定义和在vite配置里定义也不行,在vite配置文件里配置也不行,最后发现是'@originjs/vite-plugin-commonjs'插件问题,将timsdk的包转出问题了,人家本来是好的。目前该插件还有部分语法不支持,而且感觉不成熟,我一些注释掉的代码也会转换报错,先把它注释掉并运行
7,运行后报错require is not defined(解决完这个基本能把代码跑起来了)
api.js:10 Uncaught ReferenceError: require is not defined
at api.js:10:18
vite不支持require,能import引入的尽量用import吧,因为viteCommonjs造成了上一个报错还无法使用,又暂时还没有找到其他的扩展可以很好的处理这个问题。 注:不过require.context不用手动做处理,有ViteRequireContext帮我们解决。 解决: 将源代码中的require替换为import。
8,本地图片引入问题,需要兼容webpack与vite。参考:
代码(这里的代码在webpack打包时还有问题,下面会说到)
// 获取本地图
function getLocalAssetsImages(url) {
if (process.env.VITE) {
// return new URL(`/src/${url}`, import.meta.url).href
return `${location.origin}/src/${url}`
} else {
return require(`@/${url}`)
}
}
9,webpack打包报警告
webpack打包后发现一堆警告
搜索了很多博客,最终发现发现是eslint和node版本问题github.com/SublimeLint…
找到合适的eslint版本和相关依赖包并升级"eslint": "^3.19.0", =》 "eslint": "^7.5.0"
升级完eslint运行出现了很多报错,很多确实存在问题,批量修复了,但是有些规则自动修复不了,而且项目又大又老文件成千上万个,就暂时屏蔽掉了,遇到一个再改一个
10,webpack打包成功但是分包功能丢失了
基本改造完成后,vite和webpack都可以正常运行,但是webpack打包出来原来的分包功能没有了,而且连一些报了一些readme警告,之前都是没有的。
排查:
1,因为升级了node等,我第一时间反应是不是包组件的兼容问题,找了很多相关的babel包版本,比如babel-plugin-dynamic-import-node,babel-plugin-import,但是都不行,后面直接对比之前的版本,甚至直接用之前的node_models包都不行。
2,后面发现想想一些readme文件根本没引用都报了错,应该是某个地方的代码把它引入了,果然发现之前的一处地方,为了兼容webpack和vite取本地图片,写了一个方法,
// 获取本地图
function getLocalAssetsImages(url) {
if (process.env.VITE) {
// return new URL(`/src/${url}`, import.meta.url).href
return `${location.origin}/src/${url}`
} else {
return require(`@/${url}`)
}
}
这种时候(require(@/${url}
))静态分析并不能确切的知道打包src(@)下的哪个文件。此时webpack会打包src下的所有文件。所以会看到'./src ^./.*$ '这样的路径,使用require.context引入到具体文件夹下解决,参考segmentfault.com/q/101000001…
// 获取本地图
function getLocalAssetsImages(url) {
if (process.env.VITE) {
// return new URL(`/src/${url}`, import.meta.url).href
return `${location.origin}/src/${url}`
} else {
let imgNameSrc = ``
if (url) {
let params = url.split('/')
let imgName = params[params.length - 1]
imgNameSrc = `./${imgName}`
}
let requireContext = require.context('@/assets/img/function', false)
return requireContext(`${imgNameSrc}`)
}
}
11,打包后发布有一个404 main.js空包
由于vite需要引入main.js, webpack打包出来后,会加载这个空包,在html里判断一下,是webpack的时候不加载空包
import { createHtmlPlugin } from 'vite-plugin-html'
plugins: [
createHtmlPlugin({
inject: {
data: {
process: ''
}
}
})
]
<!-- process 在webpack内有,在vite内没有,通过createHtmlPlugin注入process: '', 是vite的时候才加载/src/main.js-->
<% if (process) { %>
<% } else {%>
<script type="module" src="/src/main.js"></script>
<% } %>
12,其他问题
其他插件版本问题报错
12,其他优化
懒加载
本来是使用html cdn引入,首屏非必须的包通过使用懒加载,如下包均优化
echarts,vconsole,vue-video-player,vue-video-custom-theme.css,video.min.js,video-js.css
13,最终成果
升级完成项目启动由约3min多减少约2s内, 代码更新效果时间约10s减少到无感, 代码包体积减少20MB, 首屏加载减少0.7s
打包体积旧
打包体积新(升级了node等,意外收获)
webpack冷启动
vite冷启动
webpack热更新
vite热更新无感
14,参考文章
成功解决:Can‘t find Python executable “python“, you can set the PYTHON env variable. - 郑-某 - 博客园
Error: Can't find Python executable "python", you can set the PYTHON env variable.解决办法 - 简书
(21条消息) 【Node Sass version 8.0.0 is incompatible with ^4.0.0.问题解决】_悰小风子的博客-CSDN博客
vite 不支持requrie require is not defined - 简书
(21条消息) vite配置eslint_ZGSouth的博客-CSDN博客
[Bug]: SyntaxError: Cannot use 'import.meta' outside a module · Issue #12183 · jestjs/jest · GitHub
(24条消息) vue3 vite版本 引入本地静态图片的方式_vue3引入本地图片_xiexikk的博客-CSDN博客
踩坑日记:如何修复“Issues with peer dependencies found ”错误 - 知乎
(24条消息) 详细记录前端项目使用import懒加载组件打包失败的踩坑之路_YorcentLuo的博客-CSDN博客
javascript - webpack将打包目录下的md、html文件解析了 - SegmentFault 思否
(24条消息) js中动态获取页面的script地址,并动态给他添加script标签和地址,解决页面白屏问题_妍崽崽@的博客-CSDN博客
配置antd的externals之后,antd还是会被打包进去 🐛[BUG] · Issue #5720 · ant-design/ant-design-pro · GitHub
(25条消息) vue2x版本index.html种获取环境变量_vue index.html 如何获取环境变量_momo_mom177的博客-CSDN博客
转载自:https://juejin.cn/post/7253816086679093308