有人可以解释Webpack的CommonsChunkPlugin

我得到了CommonsChunkPlugin查看所有入口点的一般要点,检查它们之间是否有常见的包/依赖关系,并将它们分离到它们自己的包中。

所以,我们假设我有以下configuration:

 ... 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 bundle中。 很好,但不理想。

  • 情况2:如果我通过{ name : 'vendors' }我将得到以下的包文件:

    • entry1.bundle.js其中包含来自entry1.js的完整代码,这是jquery一个需求,不包含运行时
    • entry2.bundle.js其中包含来自entry2.js的完整代码,这是jquery一个需求,不包含运行时
    • vendors.bundle.js其中包含从jquerysome_jquery_plugin完整的代码,并包含运行时。

    通过这种方式,我们再次得到了一些更小的bundle,但运行时现在被包含在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包含每个其他包的需求并包含运行时

    通过这种方式,我们最终得到了一些更小的包,运行时包含在manifest包中。 这是理想的情况。

我不明白/我不知道我明白

  • 案例2中,为什么我们最终得到了包含公共代码( jquery )和vendors条目( some_jquery_plugin )中剩余的任何一个的捆绑包? 根据我的理解, CommonsChunkPlugin在这里所做的是收集了通用代码( jquery ),并且由于我们强制它将其输出到vendors捆绑包,所以它将通用代码“合并”到vendors捆绑包中包含来自some_jquery_plugin的代码)。 请确认或解释。

  • 案例3中,我不明白当我们将{ names : ['vendors', 'manifest'] }传递给插件时发生了什么。 为什么/如何vendors捆绑保持不变,包含jquerysome_jquery_plugin ,当jquery显然是一个共同的依赖,为什么生成的manifest.bundle.js文件创build它的方式创build(需要所有其他包并包含运行时)?

这就是CommonsChunkPlugin工作原理。

一个普通的块“接收”几个入口块共享的模块。 在Webpack存储库中可以find一个复杂configuration的好例子。

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

当定义几个常用块时,它们按顺序处理。 在你的情况3,就像运行插件两次。 但是请注意, CommonsChunkPlugin可以有一个更复杂的configuration(minSize,minChunk等),影响模块移动的方式。

情况1:

  1. 有3个entry块( entryentry2vendors )。
  2. 该configuration将公用块设置为公共块。
  3. 这个插件处理公共块(因为块不存在,它被创build):
    1. 它收集在其他块中entry2使用的模块: entry1entry2entry2使用jquery以便将模块从这些块中移除并添加到commons块中。
    2. entry2块被标记为entry块,而entryentry2vendors块被作为entry取消。
  4. 最后,由于commons chunk是一个entry块,它包含运行时和jquery模块。

情况2:

  1. 有3个entry块( entryentry2vendors )。
  2. configuration将vendors块设置为公共块。
  3. 该插件处理vendors常见块:
    1. 它收集在其他块中entry2使用的模块: entry1entry2使用jquery以便从这些块中删除模块(注意,由于vendors块已经包含它,因此不会将其添加到vendors vendors块)。
    2. vendors块被标记为entry块,而entry1entry2块被作为entry取消标记。
  4. 最后,由于vendors块是一个entry块,它包含运行时和jquery / jquery_plugin模块。

案例3:

  1. 有3个entry块( entryentry2vendors )。
  2. configuration将vendors块和manifest块设置为常用块。
  3. 该插件创buildmanifest块,因为它不存在。
  4. 该插件处理vendors常见块:
    1. 它收集在其他块中entry2使用的模块: entry1entry2使用jquery以便从这些块中删除模块(注意,由于vendors块已经包含它,因此不会将其添加到vendors vendors块)。
    2. vendors块被标记为entry块,而entry1entry2块被作为entry取消标记。
  5. 该插件处理manifest公共块(因为块不存在,它被创build):
    1. 它收集在其他块中多次使用的模块:由于没有多次使用模块,所以没有模块被移动。
    2. manifest块被标记为entry块,而entryentry2vendors被标记为entry
  6. 最后,由于manifest块是一个entry块,它包含运行时。

希望能帮助到你。