webpack-CommonsChunkPlugin

官方文檔:

CommonsChunkPlugin

new webpack.optimize.CommonsChunkPlugin(options)
  • options.name or options.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 and options.async or options.children is set all chunks are used, otherwise options.filename is used as chunk name.

公共塊的塊名稱。可以通過傳遞現有塊的名稱來選擇現有塊。如果傳遞一個字符串數組,這等于為每個塊名稱多次調用插件,如果省略并且options.asyncoptions.children設置為使用所有塊,則使用options.filename作為塊名。

  • options.filename (string): The filename template for the commons chunk. Can contain the same placeholder as output.filename. If omitted the original filename is not modified (usually output.filename or output.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 of options.name and sibling of options.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]
  • 第三個應該是對的

參考

  1. 官網說明
  2. webpack/examples
  3. 知乎-怎么分別打包第三方庫,公用組件和業務代碼
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容