本文講解的是最近在做的一個(gè)多頁(yè)面項(xiàng)目,結(jié)合webpack4的splitChunks進(jìn)行代碼包分拆的過(guò)程
項(xiàng)目框架

項(xiàng)目有home和topic兩個(gè)入口文件,主要包括:
兩個(gè)入口文件都用react-loadable做了異步加載
import Loadable from 'react-loadable';...const LoadableLogin = Loadable({ loader: () => import('../../common/components/login'), loading: Loading,});...webpack部分配置相關(guān)如下:
module.exports = { ... mode: 'production', entry: { // 多入口 home: './src/home', topic: './src/topic', }, output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, }, plugins: [ new HtmlWebpackPlugin({ // home頁(yè)面 filename: 'home.html', template: './template.html', }), new HtmlWebpackPlugin({ // topic頁(yè)面 filename: 'topic.html', template: './template.html', inject: true, }), ], ...}splitChunks
chunks:
minSize: 文件最小打包體積,單位byte,默認(rèn)30000
比如說(shuō)某個(gè)項(xiàng)目下有三個(gè)入口文件,a.js和b.js和c.js都是100byte,當(dāng)我們將minSize設(shè)置為301,那么webpack就會(huì)將他們打包成一個(gè)包,不會(huì)將他們拆分成為多個(gè)包。
比如說(shuō)某個(gè)項(xiàng)目下有三個(gè)入口文件,a.js和b.js和c.js都是100byte,當(dāng)我們將minSize設(shè)置為301,那么webpack就會(huì)將他們打包成一個(gè)包,不會(huì)將他們拆分成為多個(gè)包。
automaticNameDelimiter: 連接符
假設(shè)我們生成了一個(gè)公用文件名字叫vendor,a.js,和b.js都依賴他,并且我們?cè)O(shè)置的連接符是"~"那么,最終生成的就是 vendor~a~b.js
maxInitialRequests 入口點(diǎn)處的最大并行請(qǐng)求數(shù),默認(rèn)為3
如果我們?cè)O(shè)置為1,那么每個(gè)入口文件就只會(huì)打包成為一個(gè)文件
maxAsyncRequests 最大異步請(qǐng)求數(shù)量,默認(rèn)5
如果我們?cè)O(shè)置為1,那么每個(gè)入口文件就只會(huì)打包成為一個(gè)文件
優(yōu)先級(jí)關(guān)系
maxInitialRequest / maxAsyncRequests <maxSize <minSize。
cacheGroups 定制分割包的規(guī)則
test可以配置正則和寫入function作為打包規(guī)則。其他屬性均可繼承splitChunks,這里必須說(shuō)一下 priority,設(shè)置包的打包優(yōu)先級(jí),非常重要! (后面結(jié)合實(shí)踐)
minChunks
最少引入的次數(shù)
實(shí)踐
我們以一個(gè)最簡(jiǎn)單的配置開始,將公共代碼打包出來(lái)
splitChunks: { chunks: 'all', // initial、async和all minSize: 30000, // 形成一個(gè)新代碼塊最小的體積 maxAsyncRequests: 5, // 按需加載時(shí)候最大的并行請(qǐng)求數(shù) maxInitialRequests: 3, // 最大初始化請(qǐng)求數(shù) automaticNameDelimiter: '~', // 打包分割符 name: true, cacheGroups: { vendors: { // 打包兩個(gè)頁(yè)面的公共代碼 minChunks: 2, // 引入兩次及以上被打包 name: 'vendors', // 分離包的名字 chunks: 'all' }, } },兩個(gè)入口文件的公共代碼被打包到vendor文件夾下面,包括echarts d3 amcharts等一些三方包和src下的公共代碼。

這當(dāng)然不是我們想要的結(jié)果!存在以下問(wèn)題:
我們修改cacheGroups為:
cacheGroups: { vendors: { // 項(xiàng)目基本框架等 chunks: 'all', test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/, priority: 100, name: 'vendors', }, 'async-commons': { // 異步加載公共包、組件等 chunks: 'async', minChunks: 2, name: 'async-commons', priority: 90, }, commons: { // 其他同步加載公共包 chunks: 'all', minChunks: 2, name: 'commons', priority: 80, }, }
這次webpack幫我們打出來(lái)的包主要有:
這里說(shuō)兩個(gè)需要注意的地方:
ok!按照我們的要求,這樣首次頁(yè)面加載只會(huì)引入vendors,commons包,而不會(huì)引入async-common包,還是挺棒的!追求更精致的我們,再認(rèn)真想想,是不是還可以做一些更好的優(yōu)化?
到目前為止我們打包文件的打包是這樣的:

用gzip壓縮后,最大的async-common包有391kb。公司說(shuō)最近因?yàn)橐恍顩r,布置到生產(chǎn)后速度慢的時(shí)候,有時(shí)候只能有20kb/s的下載速度==。。。。于是繼續(xù)split!
分析一下:
修改
cacheGroups: { vendors: { // 基本框架 chunks: 'all', test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/, priority: 100, name: 'vendors', }, d3Venodr: { // 將體積較大的d3單獨(dú)提取包,指定頁(yè)面需要的時(shí)候再異步加載 test: /d3/, priority: 100, // 設(shè)置高于async-commons,避免打包到async-common中 name: 'd3Venodr', chunks: 'async' }, echartsVenodr: { // 異步加載echarts包 test: /(echarts|zrender)/, priority: 100, // 高于async-commons優(yōu)先級(jí) name: 'echartsVenodr', chunks: 'async' }, 'async-commons': { // 其余異步加載包 chunks: 'async', minChunks: 2, name: 'async-commons', priority: 90, }, commons: { // 其余同步加載包 chunks: 'all', minChunks: 2, name: 'commons', priority: 80, }, }
當(dāng)然,每次修改后,需要在htmlWebpackPlugin中配置chunk需要的包
plugins: [ new HtmlWebpackPlugin({ // home頁(yè)面 filename: 'home.html', template: './template.html', chunks: ['vendors', 'commons', 'home'], }), new HtmlWebpackPlugin({ // topic頁(yè)面 filename: 'topic.html', template: './template.html', chunks: ['vendors', 'commons', 'topic'], }), ],后期還做了其他的拆分和優(yōu)化,大概最大的包保持在100k左右,當(dāng)然也不建議拆的特別小,因?yàn)闉g覽器http1可能一次性支持6次下載文件,太多可能會(huì)適得其反。大家可以根據(jù)自己的項(xiàng)目做不同的拆分方法,總而言之,就是為了讓項(xiàng)目更完美的在線上運(yùn)行,給用戶更好的體驗(yàn)~
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注