Webpack 4 打包优化(CRA 项目)
以 react-app-rewired
+ customize-cra
方案为例
使用 dayjs 替换 moment
sh
yarn add -D antd-dayjs-webpack-plugin
# OR
npm install -D antd-dayjs-webpack-plugin
修改 config-overrides.js
文件
js
const { override, addWebpackPlugin } = require('customize-cra')
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin')
module.exports = override(addWebpackPlugin(new AntdDayjsWebpackPlugin()))
修改 项目入口 index.js
文件
js
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
dayjs.locale('zh-cn')
相关资料
修改 optimization 配置
原因
- Webpack 4 默认分包配置
- 新的
chunk
可以被共享,或者模块来自于node_modules
文件夹 - 新的
chunk
体积大于30kb
(在进行min+gz
之前的体积) - 当按需加载
chunks
时,并行请求的最大数量小于或等于5
个 - 当加载初始化页面时,并发请求的最大数量小于或等于
3
个
- 新的
- CRA 默认配置只有
chunks
和name
优化过程
1. 在 CRA 默认配置下
通过分析可以看到最终包大小为 5.43MB,同时 antd 的 table 组件被重复打包了多次,这就不符合默认配置的规则 1 和规则 2
2. 修改 splitChunks.maxAsyncRequests 为 10 时
通过分析可以看到最终包大小为 2.65MB,同时 antd 的 table 被分离了出来,这说明 Webpack 4 默认分包规则中后面两条并行请求限制规则会影响前两条规则
所以 Webpack 4 中上述配置造成的影响: 一个组件被多个页面,这个组件会被打包到每个页面的 bundle
中,如果这个组件够小,我们可以忽略不计;但是在后台管理系统这种场景下,这个默认的打包配置非常不合理了,我们在使用 antd
的 table
组件时,这个组件在 min+gz
前有 66kb,在默认配置下会走 【新的 chunk
可以被共享,或者模块来自于 node_modules
文件夹】 这条策略,但是因为还有并行请求这条策略的限制,当并行请求超过 5
时,还是会把 table
组件打包到页面的 bundle
中,这样就十分浪费资源,所以就需要我们优化这个默认策略了
缓存组配置
- 分离不常更新的
node_modules
模块- 基础库
- 第三方 ui 组件库
- 根据上一步分离的模块大小判断具体分几个包
- 在细分缓存组配置时要考虑
HTTP 1.x
的并发限制
修改 config-overrides.js
文件
js
const { override } = require('customize-cra')
const customWebpackConfig = (config) => {
// 不生成 runtime-main
config.optimization.runtimeChunk = false
// 配置缓存组
config.optimization.splitChunks = {
chunks: 'all',
cacheGroups: {
// react 相关基础库
libs: {
test: /[\\/]node_modules[\\/](react|react-dom|react-router(-dom)?)[\\/]/,
name: 'libs',
chunks: 'all',
enforce: true, // 忽略 splitChunks.minSize、splitChunks.minChunks、splitChunks.maxAsyncRequests 和 splitChunks.maxInitialRequests 选项,并始终为此缓存组创建 chunk
priority: 100 // 一个模块可以属于多个缓存组。分包优化将优先考虑具有更高 priority(优先级)的缓存组
},
// antd 中的 rc 模块
rc: {
test: /[\\/]node_modules[\\/]rc-/,
name: 'rc',
chunks: 'all',
enforce: true,
priority: 90
},
// antd 和 @ant-design 图标
antd: {
test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
name: 'antd',
chunks: 'all',
enforce: true,
priority: 90
},
// 其他 node_modules 包
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
enforce: true
}
}
}
return config
}
module.exports = override(customWebpackConfig)