webpack4 splitChunkPlugin配置介紹
前言
webpack4刪除了CommonsChunkPlugin插件,它使用內(nèi)置API optimization.splitChunks和optimization.runtimeChunk,這意味著webpack會默認(rèn)為你生成共享的代碼塊,splitchunk的配置非常靈活,讓我們一起看一下他的配置。
原文閱讀:https://zhangzippo.github.io/posts/2019/04/20/_20webpacksplitchunk.html
基本配置項與commonsChunkPlugin大同小異,下方是啟用mode=production后,splitChunk的默認(rèn)配置:
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
cacheGroups中的配置默認(rèn)會繼承外部的配置,但是有3哥配置是每個cacheGroup獨有的,分別為test, priority 和 reuseExistingChunk,test支持正則匹配路徑,priority表示某個文件被命中多個規(guī)則時采用哪個cacheGroup,reuseExistingChunk表示如果當(dāng)前塊包含已經(jīng)從主bundle中分離出來的模塊,那么它將被重用,而不是生成一個新的模塊,一般設(shè)置為 true。從默認(rèn)配置可以看出會默認(rèn)將代碼中從node_modules中引用的的代碼按規(guī)則抽離出來。可以對optimization.splitChunks.cacheGroups.default或者optimization.splitChunks.cacheGroups.verndor為false以放棄使用默認(rèn)的配置。
實際上cacheGroups中的配置只是對我們文件分離的細(xì)化配置,我們主要關(guān)心的配置項目主要是chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests
開始分析
我們一個配置一個配置的過,首先來看chunks屬性
chunks
默認(rèn)作用于異步chunk,值為all/initial/async/function(chunk){}幾類,當(dāng)值為function時,第一個參數(shù)是遍歷所有入口chunk的chunk模塊,我們可以通過判斷chunk的名字來按需處理。我們這里主要講前三個配置。為了我們后面容易分析,我們這里采取一個用例如下圖所示:

我們新建兩個文件testA.js和testB.js,他們共同靜態(tài)引用Vue,共同動態(tài)引用qs,testA靜態(tài)引用lodash,testB靜態(tài)引用lodash.
代碼結(jié)構(gòu)如下:
testA.js
import Vue from 'vue'
import lodash from 'lodash'
import('query-string').then(component=>{
console.log(component)
})
console.log(lodash.add(1))
new Vue({
el: '#app',
template: '<h1>qewqwe<h1/>',
})
testB.js
import Vue from 'vue'
import('query-string').then(component=>{
console.log(component)
})
import('lodash').then(component=>{
console.log(component)
})
new Vue({
el: '#app',
template: '<h1>qewqwe<h1/>',
})
我們僅切換chunks的配置看看現(xiàn)象:首先是默認(rèn)的async,我們通過Bundle Analyzer可以看到只有異步引入的包被提取了出來

接著我們設(shè)置chunks選項為all,我們可以看到不管是異步引用還是靜態(tài)引用的包都被提取了出來,并且引用方式不同的lodash只被提取出了一次(實際上靜態(tài)引用被提取出來還是要滿足一些條件的,我們后面再講)文件命名上,走的是默認(rèn)配置,靜態(tài)引用的包的名字為verdor加~符號跟引用的包名加chunkhash

接著我們再看當(dāng)設(shè)置為initial時的情況,可以看到qs被提取,vue被提取,而lodash被提取了兩次,產(chǎn)生了重復(fù)的代碼。

minSize與maxSize
這兩個配置成對出現(xiàn),字面意思就可以看出來是滿足相應(yīng)大小的包才會被提取出來,單位是字節(jié),從上面的默認(rèn)配置中我們可以得知,minSize的值為30000,也就是說小于這個數(shù)的包不會被提取而是會被打到引用的文件中去,maxSize與之相反,但優(yōu)先級小于minSize,另外值得注意的是,這兩個值只對靜態(tài)引入的公共包有影響,對于異步引入的包,不管大小多少哪怕minSize設(shè)置的很大,也同樣是會被提取出來的,大家可以自行嘗試。
minChunks
與上面兩個配置一樣,同樣只作用于靜態(tài)引入的情況,控制包被引用的次數(shù)來決定是否提取公共包,從上面的默認(rèn)配置中我們得知默認(rèn)是只要被引用的node_modules中的包就會被提取,當(dāng)我們放大為3時,我們可以看到vue并不會被提取出來了。
maxInitialRequests
簡單來講就是每一個入口文件打包完成后最多能有多少個模塊組成(1.都打到一起,1以上:可以拆分,這個數(shù)值不包括入口文件(entrys)本身)舉個例子:像剛才我們的引用方式,當(dāng)我們設(shè)置為1時,我們可以看到我們的html模版中的引用只引用了testA和testB,也就是模版最多引入這兩個文件,其他都會被合并,當(dāng)我們增加之后就會在這兩個入口文件的基礎(chǔ)上增加引入的數(shù)量,也就從testA與testB中抽離出了公共代碼。具體現(xiàn)象大家可以設(shè)置完試試看。
maxAsyncRequests
這個配置的現(xiàn)象是最難以琢磨的,我至現(xiàn)在也沒能明白其具體含義,按字面意思理解,我理解為如果異步引用的包的數(shù)量超過了maxAsyncRequests的設(shè)置,那么異步的包就會被合并,然而事實上現(xiàn)象并非如此,即使設(shè)置的很小設(shè)置成1,異步引入的包還是會生成一個個獨立的被提取出來,我嘗試去github上提問,看到作者只回復(fù)了一句話:
It limits the requests per import()

可能本人比較愚鈍,尚不能參破其中奧妙
優(yōu)先級
有時我們在配置時常常發(fā)生不生效或者與預(yù)想不同的結(jié)果,往往時由于以上的屬性的優(yōu)先級不同造成的,以上屬性的優(yōu)先級為:
minSize > maxSize > maxInitialRequest/maxAsyncRequests