craco + webpack 4 升 5
我的项目使用 craco + react 开发
我的 package.json
json
{
// ......
"dependencies": {
"@ant-design/icons": "^4.7.0",
"antd": "^4.17.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@craco/craco": "^6.1.1",
"react-scripts": "^4.0.3"
}
}
想要升级到 webpack 5,此篇blog记录升级过程。
更新包版本
- 直接
npm install webpack@latest
尝试build
- 执行
npm run build
报错出现:
- 按报错信息尝试使用
export SKIP_PREFLIGHT_CHECK=true && npm run build
还是报错:
升级其他依赖库
-
那就老老实实的升级一下
npm install react-scripts@latest
有一些warn, 但是不要紧
-
再次执行build,
npm run build
执行了很长时间,然后报错,内存直接超了
-
尝试把内存开到 8G ,
npm run build --max-old-space-size=8000
,还是一样报错我的虚拟机只有8G内存,极限了。而且不应该呀,编译怎么需要这么多内存
使用process插件打印进度信息
webpack 自带了ProgressPlugin, 加到 craco.config.js 中
javascript
const webpack = require('webpack');
function configureWebpack(webpackConfig, {env, paths}) {
const processPlugin = new webpack.ProgressPlugin({
activeModules: false,
entries: true,
handler(percentage, message, ...args) {
console.info(percentage, message, ...args);
},
modules: true,
});
webpackConfig.plugins.push(processPlugin);
return webpackConfig;
}
module.exports = {
webpack: {
configure: configureWebpack,
},
};
-
再执行
npm run build
, 就可以看到进度信息:
发现:
- TerserPlugin:执行了非常久。 这是一个代码压缩插件,webpack v5 开箱即带,应该没有问题。
- 在SourceMapDevToolPlugin 阶段报错。SourceMap 就是一个信息文件,里面储存着代码的位置信息。 这种文件主要用于开发调试,现在代码都会经过压缩混淆,这样报错提示会很难定位代码。 通过SourceMap 能快速定位到源代码,并进行调试。 通常情况SourceMap 在开发环境开启,线上环境关闭。
-
修改
craco.config.js
,不执行source map,将 devtool 改为undefined,重试。 果然成功。
javascript
function configureWebpack(webpackConfig, {env, paths}) {
// ...... 省略
webpackConfig.devtool = undefined;
return webpackConfig;
}
到底需要多少内存
虽然上线已经成功了,但是这样不是办法,source_map在开发阶段是必须的。我们还是要彻底解决这个问题。
首先,我们来验证一下 是内存真的不够大还是有内存溢出的BUG,我找了一个大内存的机器试了一下,还真能跑通,npm内存使用最高时达到 12G
。
网上查了各种资料没有说webpack5会使用这么大的内存。都是说webpack5打包更小更快。
结果我的又慢又占内存,build结果更大。
分析构建产出
使用webpack-bundle-analyzer插件,分析build结果,
配置方法参考: https://www.jianshu.com/p/77c0b68c9f13
-
老环境效果:
-
新环境效果
发现 新的构建产出中, 每个入口文件(这个项目是多页应用)都用很多modules, 而老的构建中则没有。
点击左上角箭头,展开concatenated :
效果:
发现这些都是基础antd组件。
结论:新构建没有将公共依赖库分离。
添加 splitChunk
代码分离 splitChunk 是非常常用的优化方式,webpack4开始就已经可以直接使用:https://webpack.docschina.org/plugins/split-chunks-plugin/
不清楚为什么升级之后就没有这个参数了,打印craco最终的webpack_conf看一下,
javascript
function configureWebpack(webpackConfig, {env, paths}) {
// ...... 省略
console.log(webpackConfig);
return webpackConfig;
}
果然少了splitChunk插件。
老环境输出 | 新环境输出 |
---|---|
那就自己加上吧:
javascript
function configureWebpack(webpackConfig, {env, paths}) {
// ...... 省略
webpackConfig.optimization.splitChunks = {
chunks: 'all',
name: false
};
console.log(webpackConfig);
return webpackConfig;
}
重试
npm run build
,之前的问题全部解决:速度 3min -> 2min, 大小 70 -> 2, 内存 12g -> 1.2g
总结
- react-scripts 的这一版升级,有点坑呀,这么重要的插件都没有装。
- 不过这个splitChunk插件尽然能有如此大的提升,确实出乎意料。
- 分析一下 应该是生成source_map的过程会很慢,很占内存。开启chunk后,单个chunk变小,也少了很多重复编译,所以快了。
- webpack4 升 5本身的成本较低,几乎不用修改。
记录一些好文章:
- 前端工程化学习笔记:https://static.kancloud.cn/cyyspring/webpack/1857794
- webpack性能优化方案: https://yejiwei.com/post/98
- webpack性能优化(2):splitChunks用法详解: https://zhuanlan.zhihu.com/p/615064733