有人可以解释一下Webpack的CommonsChunkPlugin

时间:2016-09-17 14:53:35

标签: javascript webpack bundle webpack-plugin commonschunkplugin

我得到了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的参数,以下任何一种情况都会发生:

  • 案例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的完整代码,包含运行时

    这样我们最终会得到一些较小的bundle,运行时包含在commons包中。相当不错但不理想。

  • 案例2 :如果我通过{ name : 'vendors' },我将收到以下捆绑文件:

    • entry1.bundle.js,其中包含entry1.js的完整代码,jquery的要求且不包含运行时
    • entry2.bundle.js,其中包含entry2.js的完整代码,jquery的要求且不包含运行时
    • vendors.bundle.js,其中包含jquerysome_jquery_plugin的完整代码,并包含运行时。

    这样,我们最终总体上会有一些较小的包,但运行时现在包含在vendors包中。它比前一种情况稍差,因为运行时现在位于vendors包中。

  • 案例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包中。这是理想的情况。

我不明白/我不确定我理解

  • CASE 2 中,为什么我们最终得到包含公共代码(vendors)的jquery捆绑包以及vendors剩余的内容} entry(some_jquery_plugin)?根据我的理解,CommonsChunkPlugin在这里所做的是它收集了公共代码(jquery),并且由于我们强制它将其输出到vendors包,它有点&# 34;合并" vendors包中的公共代码(现在只包含some_jquery_plugin中的代码)。 请确认或解释。

  • CASE 3 中,我不明白当我们将{ names : ['vendors', 'manifest'] }传递给插件时发生了什么。当vendors显然是常见的依赖关系时,为什么/如何保持jquery包保持完整,同时包含some_jquery_pluginjquery,为什么生成的manifest.bundle.js文件创建方式(需要所有其他包并包含运行时)?

1 个答案:

答案 0 :(得分:101)

这就是CommonsChunkPlugin的工作原理。

公共块“接收”由多个条目块共享的模块。 可以在Webpack repository中找到复杂配置的一个很好的例子。

CommonsChunkPlugin在Webpack的优化阶段运行,这意味着它在内存中运行,就在密封块被封存并写入磁盘之前。

当定义了几个常见的块时,它们将按顺序处理。在你的情况3中,它就像运行插件两次。但请注意,CommonsChunkPlugin可能有更复杂的配置(minSize,minChunks等),这会影响模块的移动方式。

案例1:

  1. 有3个entry个块(entry1entry2vendors)。
  2. 配置将commons块设置为公共块。
  3. 插件处理commons公共块(因为块不存在,它被创建):
    1. 它收集在其他块中多次使用的模块:entry1entry2vendors使用jquery,因此模块将从这些块中删除被添加到commons块。
    2. commons数据块被标记为entry数据块,entry1entry2vendors数据块未标记为entry。< / LI>
  4. 最后,由于commons块是entry块,它包含运行时和jquery模块。
  5. 案例2:

    1. 有3个entry个块(entry1entry2vendors)。
    2. 配置将vendors块设置为公共块。
    3. 该插件处理vendors公共块:
      1. 它收集在其他块中多次使用的模块:entry1entry2使用jquery,因此模块将从这些块中删除(请注意,它未添加到vendors块,因为vendors块已经包含它。)
      2. vendors块被标记为entry块,而entry1entry2块未标记为entry
    4. 最后,由于vendors块是entry块,它包含运行时和jquery / jquery_plugin模块。
    5. 案例3:

      1. 有3个entry个块(entry1entry2vendors)。
      2. 配置将vendors块和manifest块设置为公共块。
      3. 该插件会创建manifest块,因为它不存在。
      4. 该插件处理vendors公共块:
        1. 它收集在其他块中多次使用的模块:entry1entry2使用jquery,因此模块将从这些块中删除(请注意,它未添加到vendors块,因为vendors块已经包含它。)
        2. vendors块被标记为entry块,而entry1entry2块未标记为entry
      5. 插件处理manifest公共块(因为块不存在,它被创建):
        1. 它收集在其他块中多次使用的模块:由于没有多次使用模块,因此不会移动任何模块。
        2. manifest块被标记为entry块,而entry1entry2vendors未标记为entry
      6. 最后,由于manifest块是entry块,它包含运行时。
      7. 希望它有所帮助。