参考文章:https://www.jb51.net/article/151976.htm
一.第一步:分析包结构
1.配置analyze工具
- umi内置该工具,通过 配置ANALYZE=1开启
package.json
"scripts": {
"analyze": "cross-env ANALYZE=1 umi build"
},
cross-env 报错不是内部或外部命令 需要独立安装 npm install -g cross-env
通过命令 npm run analyze
即可运行,默认serve:http://127.0.0.1:8888
2.问题补充
- 根据官方工具
umi-webpack-bundle-analyzer
gihub官网 (抛开umi内置该工具独立分析时),在windows系统下通过PowerShell作为命令操作时的问题:
webpack --profile --json > stats.json
webpack --profile --json | Out-file 'stats.json' -Encoding OEM
umi-webpack-bundle-analyzer bundle/output/path/stats.json
第二步 webpack-cli 不存在的拋错问题:必须使用
npm install -g webpack-cli
(yarn也会报错)
二.第二步:根据包结构图分析打包依赖
1.第一次打开未做任何配置的效果
parsed大小:vendors.js 2.51m umi.js 2.17m
gzip大小:vendors.js 790k umi.js 580k
第一次未做处理时
- 可以很明显的看到包整体是比较大的
1.一是echart和echart渲染组件zrender体积较大
2.二是moment重复打包和无用语言多余打包
3.三是antd组件的打包分散重复
- 这里贴出一份本人的config.js配置,主要通过
chainWebpack
接口处理
export default {
//base: '/',
//history: 'hash', //hash路由
//hash: true, //生成hash文件名
chainWebpack: function(config, { webpack }) {
config.merge({
optimization: {
minimize: true,
splitChunks: {
chunks: 'async',
minSize: 30000, //文件最小打包体积,单位byte,默认30000,若单个文件不满足会合并其他文件组成一个
minChunks: 2, //最小使用到次数,超过2次执行
automaticNameDelimiter: '.', //连接符
cacheGroups: {
vendors: {
// 基本框架
name: 'vendors',
test: /^.*node_modules[\\/](?!react|react-dom|antd).*$/,
chunks: 'all',
priority: 10,
},
// echartsVenodr: {
// // 异步加载echarts包
// name: 'echartsVenodr',
// test: /(echarts|zrender)/,
// chunks: 'async',
// priority: 10, // 高于async-commons优先级
// },
'async-commons': {
// 其余异步加载包
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 9,
},
commons: {
// 其余同步加载包
chunks: 'all',
minChunks: 2,
name: 'commons',
priority: 8,
},
},
},
},
});
//过滤掉momnet的那些不使用的国际化文件
config
.plugin('replace')
.use(require('webpack').ContextReplacementPlugin)
.tap(() => {
return [/moment[/\\]locale$/, /zh-cn/];
});
},
};
- 针对官方的这句话
config配置
是在config.js的这里处理:
config.js
不过在调试中出现的file commons.js don't exists in chunksMap
等错误,度娘查了好几遍也没 发现原因和解决方案,结合analyze分析图,发现chunk参数的设置与否并不影响结果,后续中我注释了这个配置。有知道原因的大佬麻烦告知一声,多谢。
splitChunks:
- splitChunks下的chunks、minSize、minChunks会在cacheGroups里的配置继承,不过cacheGroups里的配置,如minChunks:1参数的话会覆盖splitChunks下的minChunks: 2配置,优先级高于splitChunks
chunks:
- all: 不管文件是动态还是非动态载入,统一将文件分离。当页面首次载入会引入所有的包
- async: 将异步加载的文件分离,首次一般不引入,到需要异步引入的组件才会引入。
- initial:将异步和非异步的文件分离,如果一个文件被异步引入也被非异步引入,那它会被打包两次(注意和all区别),用于分离页面首次需要加载的包。
priority:
- 设置包的打包优先级,这里解释一下,基本是在两个包同时包含一个插件会用到,priority大的会打包到这个里面。
2.第二次打开配置后的效果
- 省略了中间的多次调整,最后结果:
抽离出了echart,并把异步加载归类到async-commons
核心思想:把首页加载时的必用框架react-dom等组件配置到vendors,其他echart等在固定页面打开时加载时引用的地方放入异步加载包里。
externals: {
echarts: 'window.echarts',
// d3: 'window.d3',
}
- moment的优化处理
//过滤掉momnet的那些不使用的国际化文件
config.plugin("replace").use(require("webpack").ContextReplacementPlugin).tap(() => {
return [/moment[/\\]locale$/, /zh-cn/];
});
parsed大小:vendors.js 526k umi.js 1.54m
gzip大小:vendors.js 143k umi.js 425k
第二次打开
3.第三次配置修改
~ 抽点时间再补充下
把修改的部分粘出来
有几点问题说明下:
1.vendors 修改了test的验证范围,发现结果也没有很大变化,不知道是哪里除了问题,而且vendors包变的很小,umi包反而比较大。
2.default:这里的 reuseExistingChunk: true
复用其他chunk内已拥有的模块 当chunks引用了已经存在的被抽离的chunks时不会新创建一个chunk而是复用chunk。参考文章
这里贴一个default minChunks配置的效果:
minChunks:1
minChunks:2
minChunks:2
cacheGroups: {
vendors: {
// 基本框架
name: 'vendors',
test: /[\\/]node_modules[\\/](lodash|re-select|moment)[\\/]/,
chunks: 'all',
priority: 10,
},
antdesigns: {
name: 'antdesigns',
chunks: 'all',
test: /[\\/]node_modules[\\/](@ant-design|antd)[\\/]/,
priority: 10,
},
'async-commons': {
// 其余异步加载包
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 9,
},
default: {
name: 'default',
minChunks: 1,
priority: -1,
reuseExistingChunk: true, //
},
},
- 补充:后来调整发现这里的效果配置并不理想,看下一条。
效果:
第三次配置
第三次配置
network耗时和size
nginx开启gzip后效果
最终效果感觉是很明显的,在网络带宽一般的情况下,之前首屏加载大概6-8s左右,现在是1-3s内基本ok,还是很明显的,同时也可以节约服务器带宽,不过相应的对CPU的消耗会有所增加,这个根据实际情况考虑。
这里贴个nginx相关参考链接 :https://www.cnblogs.com/kevingrace/p/10018914.html
4.第四次配置修改
- 这里又抽空弄了一下,感觉之前有些地方稀里糊涂的,配置和结果并不理想。
配置如下:
vendors: {
// 基本框架
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
// chunks: 'all',
priority: 10,
},
antdesigns: {
name: 'antdesigns',
chunks: 'all',
test: /[\\/]node_modules[\\/](@ant-design|antd)[\\/]/,
priority: 11,
},
jsdk: {
name: 'jsdk',
chunks: 'initial',
test: /[\\/]node_modules[\\/](china-division|dingtalk-jsapi|lodash|moment)[\\/]/,
priority: 11,
},
'async-commons': {
// 其余异步加载包
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 9,
},
default: {
name: 'default',
minChunks: 1,
priority: -1,
reuseExistingChunk: true,
},
几点说明一下:
① vendors 的 test 修改为mode_modules下的所有引入包。
② 针对vendors的配置,把 antdesigns 和 jsdk 的priority优先级调高,抽离出对应插件包模块。
③ 相应的umi.js会自动打包剩余react相关必备核心框架包。
④ 对于default的minChunks配置,线上我可能还是会改为2,当前所有page都被打包进来了。
-
效果:
第四次配置
第四次配置 Parsed
第四次配置 Gzip
这次结果基本很理想了,拆包已经很小了,包结构功能基本也比较清晰。
react/umi/dva核心模块,antd视图框架模块,lodash/moment等第三方插件,async-commons页面/default组件包模块。
不过对于vendors下的rc-table、rc-select等rc开头的插件还不是很理解,后期继续学习。
- 提醒下,本地开发调试不建议开启,适合打包线上build配置使用。
~ 暂时先这样,后面有时间再研究研究。写个记录备忘。目前还有些不明白的地方。~~
网友评论