有人能解释一下Webpack的CommonsChunkPlugin吗

gblwokeq  于 2022-12-27  发布在  Webpack
关注(0)|答案(1)|浏览(192)

我得到的一般要点是,CommonsChunkPlugin查看所有入口点,检查它们之间是否有公共的包/依赖关系,并将它们分离到自己的包中。
因此,让我们假设我有以下配置:

...
enrty : {
    entry1 : 'entry1.js', //which has 'jquery' as a dependency
    entry2 : 'entry2.js', //which has 'jquery as a dependency
    vendors : [
        'jquery',
        'some_jquery_plugin' //which has 'jquery' as a dependency
    ]
},
output: {
    path: PATHS.build,
    filename: '[name].bundle.js'
}
...

如果不使用CommonsChunkPlugin进行捆绑

我将以3个新的捆绑包文件结束:

  • entry1.bundle.js,它包含entry1.jsjquery的完整代码,并包含自己的运行时
  • entry2.bundle.js,它包含entry2.jsjquery的完整代码,并包含自己的运行时
  • vendors.bundle.js,它包含jquerysome_jquery_plugin的完整代码,并包含自己的运行时

这显然是不好的,因为我可能会在页面中加载jquery 3次,所以我们不希望这样。

如果我使用CommonsChunkPlugin进行捆绑

根据我传递给CommonsChunkPlugin的参数,将发生以下任何一种情况:

***CASE 1:**如果我传递{ name : 'commons' },我将得到以下捆绑包文件:

  • entry1.bundle.js,其中包含entry1.js的完整代码(jquery的要求),但不包含运行时
  • entry2.bundle.js,包含entry2.js的完整代码(jquery的要求),不包含运行时
  • vendors.bundle.js,包含some_jquery_plugin的完整代码(jquery的要求),不包含运行时
  • commons.bundle.js,它包含jquery中的完整代码,并包含运行时

这样我们最终得到了一些更小的包,运行时包含在commons包中。

***案例2:**如果我传递{ name : 'vendors' },我将得到以下包文件:

  • entry1.bundle.js,包含entry1.js的完整代码(jquery的要求),不包含运行时
  • entry2.bundle.js,包含entry2.js的完整代码,这是jquery的一个要求,但不包含运行时
  • vendors.bundle.js,其中包含jquerysome_jquery_plugin的完整代码,并包含运行时。

这样,我们最终得到了一些更小的bundle,但是运行时现在包含在vendors bundle中,这比上一个情况要差一些,因为运行时现在包含在vendors bundle中。

***案例3:**如果我传递{ names : ['vendors', 'manifest'] },我将得到以下包文件:

  • entry1.bundle.js,其中包含entry1.js的完整代码(jquery的要求),但不包含运行时
  • entry2.bundle.js,包含entry2.js的完整代码,这是jquery的一个要求,但不包含运行时
  • vendors.bundle.js,它包含jquerysome_jquery_plugin中的完整代码,但不包含运行时
  • manifest.bundle.js,它包含每个其他捆绑包的要求,并包含运行时

这样我们就得到了一些更小的bundle,运行时包含在manifest bundle中,这是理想的情况。

我不明白/我不确定我是否明白

  • CASE 2中,为什么我们最终得到的vendors捆绑包包含两个公共代码(jquery)以及vendors项中剩余的内容(some_jquery_plugin)?据我所知,CommonsChunkPlugin在这里所做的是收集公共代码(jquery),并且由于我们强制它将其输出到vendors bundle,因此它将通用代码“合并”到vendors bundle中(现在只包含some_jquery_plugin中的代码)。请确认或解释。
  • 案例3中,我不明白当我们将{ names : ['vendors', 'manifest'] }传递给插件时发生了什么。当jquery显然是一个公共依赖项时,为什么/如何保持vendors包的完整性,包含jquerysome_jquery_plugin,为什么生成的manifest.bundle.js文件是按照它的创建方式创建的(需要所有其他bundle并包含运行时)?
l0oc07j2

l0oc07j21#

这就是CommonsChunkPlugin的工作原理。
一个公共块"接收"由几个入口块共享的模块。在Webpack repository中可以找到一个复杂配置的好例子。
CommonsChunkPlugin在Webpack的优化阶段运行,这意味着它在内存中运行,就在块被密封并写入磁盘之前。
当定义了几个公共块时,它们会按顺序处理。在您的情况3中,这就像运行插件两次。但请注意,CommonsChunkPlugin可以有一个更复杂的配置(minSize,minChunks等),这会影响模块移动的方式。

    • 情况1:**

1.有3个entry区块(entry1entry2vendors)。
1.配置将commons块设置为公共块。
1.插件处理commons公共块(由于块不存在,因此创建):
1.它收集在其他块中多次使用的模块:entry1entry2vendors使用jquery,因此模块从这些块中删除并添加到commons块。

  1. commons块被标记为entry块,而entry1entry2vendors块未被标记为entry
    1.最后,由于commons块是entry块,因此它包含运行时和jquery模块。
    • 情况2:**

1.有3个entry区块(entry1entry2vendors)。
1.配置将vendors块设置为公共块。
1.该插件处理vendors公共块:
1.它收集在其他块中多次使用的模块:entry1entry2使用jquery,因此模块从这些块中移除(注意,它没有被添加到vendors块,因为vendors块已经包含它)。

  1. vendors块被标记为entry块,而entry1entry2块未被标记为entry
    1.最后,由于vendors块是entry块,因此它包含运行时和jquery/jquery_plugin模块。
    • 案例3:**

1.有3个entry区块(entry1entry2vendors)。
1.配置将vendors块和manifest块设置为公共块。
1.插件创建manifest块,因为它不存在。
1.插件处理vendors公共块:
1.它收集在其他块中多次使用的模块:entry1entry2使用jquery,因此模块从这些块中移除(注意,它没有被添加到vendors块,因为vendors块已经包含它)。

  1. vendors块被标记为entry块,而entry1entry2块未被标记为entry
    1.插件处理manifest公共块(由于块不存在,因此创建):
    1.它收集在其他块中多次使用的模块:由于没有模块被使用超过一次,因此没有模块被移动。
  2. manifest块被标记为entry块,而entry1entry2vendors未被标记为entry
    1.最后,由于manifest块是entry块,因此它包含运行时。

相关问题