官方文檔:
CommonsChunkPlugin
new webpack.optimize.CommonsChunkPlugin(options)
-
options.name
oroptions.names
(string|string[]
): The chunk name of the commons chunk. An existing chunk can be selected by passing a name of an existing chunk. If an array of strings is passed this is equal to invoking the plugin multiple times for each chunk name. If omitted andoptions.async
oroptions.children
is set all chunks are used, otherwiseoptions.filename
is used as chunk name.
公共塊的塊名稱。可以通過傳遞現有塊的名稱來選擇現有塊。如果傳遞一個字符串數組,這等于為每個塊名稱多次調用插件,如果省略并且options.async
或options.children
設置為使用所有塊,則使用options.filename
作為塊名。
-
options.filename
(string
): The filename template for the commons chunk. Can contain the same placeholder asoutput.filename
. If omitted the original filename is not modified (usuallyoutput.filename
oroutput.chunkFilename
).
公共塊的文件名。可以包含與output.filename相同的占位符。如果省略,原始文件名不會被修改(一般是output.filename
or output.chunkFilename
).
-
options.minChunks
(number|Infinity|function(module, count
) -> boolean): The minimum number of chunks which need to contain a module before it's moved into the commons chunk. The number must be greater than or equal 2 and lower than or equal to the number of chunks. Passing Infinity just creates the commons chunk, but moves no modules into it. By providing a function you can add custom logic. (Defaults to the number of chunks)
在模塊移動到公共塊之前需要包含該模塊的塊的最小數量。該數字必須大于或等于2且小于或等于塊的數量,設置為Infinity
只是創建公共塊,但不移動模塊。通過提供一個函數,你可以添加自定義邏輯
-
options.chunks
(string[]
): Select the source chunks by chunk names. The chunk must be a child of the commons chunk. If omitted all entry chunks are selected.
按塊名稱選擇源塊。塊必須是公共塊的子節點。如果省略,則選擇所有塊
-
options.children
(boolean
): If true all children of the commons chunk are selected
如果為true,則選擇公共塊的所有子塊(當存在code splitting的時候,入口chunk會存在多個子chunk,子chunk之間也會存在重復的引用模塊,如果該選項為true,則子chunk會將公共模塊提取到入口模塊當中去)
-
options.async
(boolean|string
): If true a new async commons chunk is created as child ofoptions.name
and sibling ofoptions.chunks
. It is loaded in parallel with options.chunks. It is possible to change the name of the output file by providing the desired string instead of true.
假如設置為true
一個新的異步commons chunk被創建為options.name的子塊和options.chunks的兄弟塊。它與options.chunks并行加載。可以通過提供所需的字符串而不是true
來更改輸出文件的名稱。
-
options.minSize
(number
): Minimum size of all common module before a commons chunk is created.
創建公共塊之前所有公共模塊的最小大小
解讀
- 這個插件主要是用來創建的chunk中提取公共的模塊單獨打包,所以主要用來做兩件事情:單獨打包公共模塊以及分離第三方依賴庫。
- 打包第三方依賴庫的原理就是
options.name
可以選擇現有的chunk,entry中將所有的第三方依賴庫放入vendor中,把minChunks設置為Infinity,其他的共有模塊就打不進來,這個vendor就作為一個公共模塊單獨出來了
案例
打包多個公共模塊
pageA.js
require("./modules/a-b-c");
require("./modules/a-b");
require("./modules/a-c");
pageB.js
require("./modules/a-b-c");
require("./modules/a-b");
require("./modules/a-c");
pageC.js
require("./modules/a-b-c");
require("./modules/a-b");
require("./modules/b-c");
adminPageA.js
require("./modules/a-b-c");
require("./modules/admin");
adminPageB.js
require("./modules/a-b-c");
require("./modules/admin");
adminPageC.js
require("./modules/a-b-c");
require("./modules/admin");
webpack.config.js
var path = require("path");
var CommonsChunkPlugin = require("../../lib/optimize/CommonsChunkPlugin");
module.exports = {
entry: {
pageA: "./pageA",
pageB: "./pageB",
pageC: "./pageC",
adminPageA: "./adminPageA",
adminPageB: "./adminPageB",
adminPageC: "./adminPageC",
},
output: {
path: path.join(__dirname, "js"),
filename: "[name].js"
},
plugins: [
new CommonsChunkPlugin({
name: "admin-commons",
chunks: ["adminPageA", "adminPageB"]
}),
new CommonsChunkPlugin({
name: "commons",
chunks: ["pageA", "pageB", "admin-commons"],
minChunks: 2
}),
new CommonsChunkPlugin({
name: "c-commons",
chunks: ["pageC", "adminPageC"]
}),
]
}
info
Hash: 295aa8d9fd845ec1d1b0
Version: webpack 2.2.0-rc.2
Asset Size Chunks Chunk Names
pageC.js 768 bytes 0 [emitted] pageC
pageB.js 567 bytes 1 [emitted] pageB
pageA.js 567 bytes 2 [emitted] pageA
adminPageC.js 544 bytes 3, 4 [emitted] adminPageC
admin-commons.js 233 bytes 4 [emitted] admin-commons
adminPageB.js 337 bytes 5 [emitted] adminPageB
adminPageA.js 337 bytes 6 [emitted] adminPageA
commons.js 6 kB 7, 8 [emitted] commons
c-commons.js 5.76 kB 8 [emitted] c-commons
Entrypoint pageA = commons.js pageA.js
Entrypoint pageB = commons.js pageB.js
Entrypoint pageC = c-commons.js pageC.js
Entrypoint adminPageA = commons.js admin-commons.js adminPageA.js
Entrypoint adminPageB = commons.js admin-commons.js adminPageB.js
Entrypoint adminPageC = c-commons.js adminPageC.js
同時打包公共模塊和vendor
有如下依賴:
- pageA
- utility1
- utility2
- pageB
- utility2
- utility3
- pageC
- utility2
- utility3
最終想產生這樣的包關系
- vendor
- webpack runtime
- vendor1
- vendor2
- common
- utility2
- utility3
- pageA
- pageA
- utility1
- pageB
- pageB
- pageC
- pageC
webpack.config.js
var path = require("path");
var CommonsChunkPlugin = require("../../lib/optimize/CommonsChunkPlugin");
module.exports = {
entry: {
vendor: ["./vendor1", "./vendor2"],
pageA: "./pageA",
pageB: "./pageB",
pageC: "./pageC"
// older versions of webpack may require an empty entry point declaration here
// common: []
},
output: {
path: path.join(__dirname, "js"),
filename: "[name].js"
},
plugins: [
new CommonsChunkPlugin({
// The order of this array matters
names: ["common", "vendor"],
minChunks: 2
})
]
};
原理就是names: ["common", "vendor"]
會將公共的部分打包進common
然后再將第三方依賴庫放進vendor中
其中有三個個疑問:
-
common
在打包的時候會不會將vendor的chunk事先排除在外 -
vendor
在打包的時候會將已經打好包的common
排除在外 -
minChunks
等參數對common、vendor
是否都有效
剛剛考慮一下,覺得上面的問題有了答案:
- 第一個不會,官網意思很明確“如果傳遞一個字符串數組,這等于為每個塊名稱多次調用插件”,所以相當于是設置了兩個CommonsChunkPlugin,但是否存在vendor打包進common(pageA等可能引用vendor,但是vendor不會引用自身,故不存在公共模塊,肯定不會打進common),當name值和entry入口相同的時候(vendor),此時就是取到抽離chunk的目的。
- 第二個其實chunks為[vendor, pageA, pageB, pageC,common]
- 第三個應該是對的