參考文章:https://www.jb51.net/article/151976.htm
一.第一步:分析包結(jié)構(gòu)
1.配置analyze工具
- umi內(nèi)置該工具,通過 配置ANALYZE=1開啟
package.json
"scripts": {
"analyze": "cross-env ANALYZE=1 umi build"
},
cross-env 報(bào)錯(cuò)不是內(nèi)部或外部命令 需要獨(dú)立安裝 npm install -g cross-env
通過命令 npm run analyze 即可運(yùn)行,默認(rèn)serve:http://127.0.0.1:8888

2.問題補(bǔ)充
- 根據(jù)官方工具
umi-webpack-bundle-analyzergihub官網(wǎng) (拋開umi內(nèi)置該工具獨(dú)立分析時(shí)),在windows系統(tǒng)下通過PowerShell作為命令操作時(shí)的問題:
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 不存在的拋錯(cuò)問題:必須使用
npm install -g webpack-cli(yarn也會(huì)報(bào)錯(cuò))
二.第二步:根據(jù)包結(jié)構(gòu)圖分析打包依賴
1.第一次打開未做任何配置的效果
parsed大小:vendors.js 2.51m umi.js 2.17m
gzip大?。簐endors.js 790k umi.js 580k


- 可以很明顯的看到包整體是比較大的
1.一是echart和echart渲染組件zrender體積較大
2.二是moment重復(fù)打包和無用語言多余打包
3.三是antd組件的打包分散重復(fù)
- 這里貼出一份本人的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,默認(rèn)30000,若單個(gè)文件不滿足會(huì)合并其他文件組成一個(gè)
minChunks: 2, //最小使用到次數(shù),超過2次執(zhí)行
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優(yōu)先級(jí)
// },
'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/];
});
},
};
- 針對(duì)官方的這句話
config配置
是在config.js的這里處理:
config.js
不過在調(diào)試中出現(xiàn)的file commons.js don't exists in chunksMap等錯(cuò)誤,度娘查了好幾遍也沒 發(fā)現(xiàn)原因和解決方案,結(jié)合analyze分析圖,發(fā)現(xiàn)chunk參數(shù)的設(shè)置與否并不影響結(jié)果,后續(xù)中我注釋了這個(gè)配置。有知道原因的大佬麻煩告知一聲,多謝。
splitChunks:
- splitChunks下的chunks、minSize、minChunks會(huì)在cacheGroups里的配置繼承,不過cacheGroups里的配置,如minChunks:1參數(shù)的話會(huì)覆蓋splitChunks下的minChunks: 2配置,優(yōu)先級(jí)高于splitChunks
chunks:
- all: 不管文件是動(dòng)態(tài)還是非動(dòng)態(tài)載入,統(tǒng)一將文件分離。當(dāng)頁面首次載入會(huì)引入所有的包
- async: 將異步加載的文件分離,首次一般不引入,到需要異步引入的組件才會(huì)引入。
- initial:將異步和非異步的文件分離,如果一個(gè)文件被異步引入也被非異步引入,那它會(huì)被打包兩次(注意和all區(qū)別),用于分離頁面首次需要加載的包。
priority:
- 設(shè)置包的打包優(yōu)先級(jí),這里解釋一下,基本是在兩個(gè)包同時(shí)包含一個(gè)插件會(huì)用到,priority大的會(huì)打包到這個(gè)里面。
2.第二次打開配置后的效果
- 省略了中間的多次調(diào)整,最后結(jié)果:
抽離出了echart,并把異步加載歸類到async-commons
核心思想:把首頁加載時(shí)的必用框架react-dom等組件配置到vendors,其他echart等在固定頁面打開時(shí)加載時(shí)引用的地方放入異步加載包里。
externals: {
echarts: 'window.echarts',
// d3: 'window.d3',
}
- moment的優(yōu)化處理
//過濾掉momnet的那些不使用的國際化文件
config.plugin("replace").use(require("webpack").ContextReplacementPlugin).tap(() => {
return [/moment[/\\]locale$/, /zh-cn/];
});
parsed大?。簐endors.js 526k umi.js 1.54m
gzip大?。簐endors.js 143k umi.js 425k


3.第三次配置修改
~ 抽點(diǎn)時(shí)間再補(bǔ)充下
把修改的部分粘出來
有幾點(diǎn)問題說明下:
1.vendors 修改了test的驗(yàn)證范圍,發(fā)現(xiàn)結(jié)果也沒有很大變化,不知道是哪里除了問題,而且vendors包變的很小,umi包反而比較大。
2.default:這里的 reuseExistingChunk: true 復(fù)用其他chunk內(nèi)已擁有的模塊 當(dāng)chunks引用了已經(jīng)存在的被抽離的chunks時(shí)不會(huì)新創(chuàng)建一個(gè)chunk而是復(fù)用chunk。參考文章
這里貼一個(gè)default minChunks配置的效果:
minChunks:1

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, //
},
},
- 補(bǔ)充:后來調(diào)整發(fā)現(xiàn)這里的效果配置并不理想,看下一條。
效果:
第三次配置
第三次配置
network耗時(shí)和size
nginx開啟gzip后效果
最終效果感覺是很明顯的,在網(wǎng)絡(luò)帶寬一般的情況下,之前首屏加載大概6-8s左右,現(xiàn)在是1-3s內(nèi)基本ok,還是很明顯的,同時(shí)也可以節(jié)約服務(wù)器帶寬,不過相應(yīng)的對(duì)CPU的消耗會(huì)有所增加,這個(gè)根據(jù)實(shí)際情況考慮。
這里貼個(gè)nginx相關(guān)參考鏈接 :https://www.cnblogs.com/kevingrace/p/10018914.html
4.第四次配置修改
- 這里又抽空弄了一下,感覺之前有些地方稀里糊涂的,配置和結(jié)果并不理想。
配置如下:
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,
},
幾點(diǎn)說明一下:
① vendors 的 test 修改為mode_modules下的所有引入包。
② 針對(duì)vendors的配置,把 antdesigns 和 jsdk 的priority優(yōu)先級(jí)調(diào)高,抽離出對(duì)應(yīng)插件包模塊。
③ 相應(yīng)的umi.js會(huì)自動(dòng)打包剩余react相關(guān)必備核心框架包。
④ 對(duì)于default的minChunks配置,線上我可能還是會(huì)改為2,當(dāng)前所有page都被打包進(jìn)來了。
-
效果:
第四次配置
第四次配置 Parsed
第四次配置 Gzip
這次結(jié)果基本很理想了,拆包已經(jīng)很小了,包結(jié)構(gòu)功能基本也比較清晰。
react/umi/dva核心模塊,antd視圖框架模塊,lodash/moment等第三方插件,async-commons頁面/default組件包模塊。
不過對(duì)于vendors下的rc-table、rc-select等rc開頭的插件還不是很理解,后期繼續(xù)學(xué)習(xí)。
- 提醒下,本地開發(fā)調(diào)試不建議開啟,適合打包線上build配置使用。
~ 暫時(shí)先這樣,后面有時(shí)間再研究研究。寫個(gè)記錄備忘。目前還有些不明白的地方。~~








