谁能解释一下 Webpack 的 CommonsChunkPlugin
Posted
技术标签:
【中文标题】谁能解释一下 Webpack 的 CommonsChunkPlugin【英文标题】:Can someone explain Webpack's CommonsChunkPlugin 【发布时间】:2017-01-25 16:01:40 【问题描述】:我知道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.js
和 jquery
的完整代码,并包含自己的运行时
entry2.bundle.js
包含来自 entry2.js
和 jquery
的完整代码,并包含自己的运行时
vendors.bundle.js
包含来自 jquery
和 some_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
的完整代码并包含运行时
这样我们最终会得到一些较小的包,并且运行时包含在commons
包中。还可以,但不理想。
案例2:如果我通过 name : 'vendors'
,我将得到以下捆绑文件:
entry1.bundle.js
包含来自 entry1.js
的完整代码,是 jquery
的要求,不包含运行时
entry2.bundle.js
包含来自 entry2.js
的完整代码,是 jquery
的要求,不包含运行时
vendors.bundle.js
包含来自 jquery
和 some_jquery_plugin
的完整代码并包含运行时。
这样,我们最终会得到一些较小的包,但运行时现在包含在vendors
包中。这比前一种情况要差一些,因为运行时现在位于 vendors
包中。
案例3:如果我通过 names : ['vendors', 'manifest']
,我将得到以下捆绑文件:
entry1.bundle.js
包含来自 entry1.js
的完整代码,是 jquery
的要求,不包含运行时
entry2.bundle.js
包含来自entry2.js
的完整代码,是jquery
的要求,不包含运行时
vendors.bundle.js
包含来自 jquery
和 some_jquery_plugin
的完整代码,但不包含运行时
manifest.bundle.js
包含所有其他捆绑包的要求并包含运行时
这样我们最终会得到一些较小的包,并且运行时包含在manifest
包中。这是理想的情况。
我不明白/我不确定我是否明白
在 CASE 2 中,为什么我们最终会得到包含公共代码 (jquery
) 和 vendors
条目 (some_jquery_plugin
) 中剩余的任何内容的 vendors
包)?据我了解,CommonsChunkPlugin
在这里所做的是它收集了公共代码 (jquery
),并且由于我们强制它输出到 vendors
包,它有点将公共代码“合并”到vendors
捆绑包(现在只包含来自some_jquery_plugin
的代码)。 请确认或解释。
在 CASE 3 中,当我们将 names : ['vendors', 'manifest']
传递给插件时,我不明白发生了什么。为什么/如何保持vendors
捆绑包保持原样,同时包含jquery
和some_jquery_plugin
,而jquery
显然是一个常见的依赖项,以及为什么生成的manifest.bundle.js
文件按照它的创建方式创建(需要所有其他包并包含运行时)?
【问题讨论】:
对于案例 1,我认为您应该指定 minChunks 属性。 从您的问题中我学到了很多,非常感谢! 非常感谢您提出这个问题并解决我一直以来对这个插件的困惑❤ 也许有人知道,这些示例在 Webpack 4 中会是什么样子? 【参考方案1】:这就是CommonsChunkPlugin
的工作原理。
一个公共块“接收”由几个入口块共享的模块。 在Webpack repository 中可以找到复杂配置的一个很好的示例。
CommonsChunkPlugin
在 Webpack 的优化阶段运行,这意味着它在内存中运行,就在块被密封并写入磁盘之前。
当定义了几个公共块时,它们会按顺序处理。在您的情况 3 中,就像运行插件两次一样。但请注意,CommonsChunkPlugin
可能具有更复杂的配置(minSize、minChunks 等),这会影响模块的移动方式。
案例 1:
-
有 3 个
entry
块(entry1
、entry2
和 vendors
)。
配置将commons
块设置为普通块。
插件处理commons
公共块(由于块不存在,所以创建):
-
它收集在其他块中多次使用的模块:
entry1
、entry2
和 vendors
使用 jquery
,因此模块从这些块中删除并添加到 commons
块中.
commons
块被标记为 entry
块,而 entry1
、entry2
和 vendors
块未被标记为 entry
。
commons
块是entry
块,它包含运行时和jquery
模块。
案例 2:
-
有 3 个
entry
块(entry1
、entry2
和 vendors
)。
配置将vendors
块设置为普通块。
插件处理vendors
公共块:
-
它收集在其他块中多次使用的模块:
entry1
和entry2
使用jquery
,因此模块从这些块中删除(注意它没有添加到vendors
块中因为vendors
块已经包含它)。
vendors
块被标记为 entry
块,而 entry1
和 entry2
块未被标记为 entry
。
vendors
块是entry
块,它包含运行时和jquery
/jquery_plugin
模块。
案例 3:
-
有 3 个
entry
块(entry1
、entry2
和 vendors
)。
配置将vendors
块和manifest
块设置为通用块。
插件创建manifest
块,因为它不存在。
插件处理vendors
公共块:
-
它收集在其他块中多次使用的模块:
entry1
和 entry2
使用 jquery
,因此模块从这些块中删除(注意它没有添加到 vendors
块中因为vendors
块已经包含它)。
vendors
块被标记为 entry
块,而 entry1
和 entry2
块未被标记为 entry
。
manifest
公共块(由于块不存在,所以创建):
-
它收集在其他块中多次使用的模块:因为没有模块被多次使用,所以没有模块被移动。
manifest
块标记为 entry
块,而 entry1
、entry2
和 vendors
未标记为 entry
。
manifest
块是 entry
块,它包含运行时。
希望对你有帮助。
【讨论】:
我想问/澄清几件事,也请在您的答案中添加这些要点:1)您能否对案例 1 进行相同的逐步解释,以便答案 1000% 完成? 2) 使用 names : ['vendors', 'manifest']
运行插件就像运行两次一样,一次使用 name : 'vendors'
,一次使用 name : 'manifest'
,对吗? 3)当我们说“插件处理一个公共块”时,我们的意思是它会在内存中创建它将在bundle.js
文件中吐出的内容,对吗? 4)在“处理所有常见块”之前,它根本没有将任何输出写入文件,它都在内存中
我还有一个问题,如果你想回答的话。假设在我上面的示例中,entry1.js
和entry2.js
在它们之间有另一个公共文件,而不是jquery
文件,我们称之为ownLib.js
。在案例 2 和案例 3 中,ownLib.js
最终会出现在 vendors.bundle.js
中,对吗?除了vendors
块之外,您将如何将供应商文件以外的常见文件分成它们自己的块?抱歉打扰了,我还在学习如何使用 webpack
是的,这是正确的:ownLib.js
将被放置在第一个公共块中。如果你想在另一个块中收集公共依赖项,你必须传递这样的东西: names : ['common', 'vendors', 'manifest']
.
好问题,好答案,好讨论。看来我终于明白了。
我花了最后 天 阅读 CommonsChunkPlugin 文档,这是我读到的第一个地方,在执行后,已处理的块“未标记为条目”。这基本上解释了我遇到的所有问题——如果我可以多次投票,我会的。以上是关于谁能解释一下 Webpack 的 CommonsChunkPlugin的主要内容,如果未能解决你的问题,请参考以下文章
谁能解释一下预定义的 GenericModel 类的这种语法? [复制]
解释一下:webpack、gulp 和 react、redux