umi vendors 包體積較大處理

參考文章:https://www.jb51.net/article/151976.htm

一.第一步:分析包結(jié)構(gòu)

1.配置analyze工具
  "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

啟動(dòng)后效果

2.問題補(bǔ)充
  • 根據(jù)官方工具 umi-webpack-bundle-analyzer gihub官網(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

第一次未做處理時(shí)

第一次未做處理時(shí)
  • 可以很明顯的看到包整體是比較大的
    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: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, //
    },
},
  • 補(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è)記錄備忘。目前還有些不明白的地方。~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容