问题
I get the general gist that the CommonsChunkPlugin looks at all the entry points, checks to see if there are common packages/dependencies between them and separates them into their own bundle.
So, let's assume I have the following 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'
}
...
If I bundle without using CommonsChunkPlugin
I will end up with 3 new bundle files:
entry1.bundle.jswhich contains the complete code fromentry1.jsandjqueryand contains its own runtimeentry2.bundle.jswhich contains the complete code fromentry2.jsandjqueryand contains its own runtimevendors.bundle.jswhich contains the complete code fromjqueryandsome_jquery_pluginand contains its own runtime
This is obviously bad because I will potentially load jquery 3 times in the page, so we don't want that.
If I bundle using CommonsChunkPlugin
Depending on what arguments I pass to CommonsChunkPlugin any of the following will happen:
CASE 1 : If I pass
{ name : 'commons' }I will end up with the following bundle files:entry1.bundle.jswhich contains the complete code fromentry1.js, a requirement forjqueryand does not contain the runtimeentry2.bundle.jswhich contains the complete code fromentry2.js, a requirement forjqueryand does not contain the runtimevendors.bundle.jswhich contains the complete code fromsome_jquery_plugin, a requirement forjqueryand does not contain the runtimecommons.bundle.jswhich contains the complete code fromjqueryand contains the runtime
This way we end up with some smaller bundles overall and the runtime is contained in the
commonsbundle. Pretty ok but not ideal.CASE 2 : If I pass
{ name : 'vendors' }I will end up with the following bundle files:entry1.bundle.jswhich contains the complete code fromentry1.js, a requirement forjqueryand does not contain the runtimeentry2.bundle.jswhich contains the complete code fromentry2.js, a requirement forjqueryand does not contain the runtimevendors.bundle.jswhich contains the complete code fromjqueryandsome_jquery_pluginand contains the runtime.
This way, again, we end up with some smaller bundles overall but the runtime is now contained in the
vendorsbundle. It's a little worse than the previous case, since the runtime is now in thevendorsbundle.CASE 3 : If I pass
{ names : ['vendors', 'manifest'] }I will end up with the following bundle files:entry1.bundle.jswhich contains the complete code fromentry1.js, a requirement forjqueryand does not contain the runtimeentry2.bundle.jswhich contains the complete code fromentry2.js, a requirement forjqueryand does not contain the runtimevendors.bundle.jswhich contains the complete code fromjqueryandsome_jquery_pluginand does not contain the runtimemanifest.bundle.jswhich contains requirements for every other bundle and contains the runtime
This way we end up with some smaller bundles overall and the runtime is contained in the
manifestbundle. This is the ideal case.
What I do not understand/I am not sure I understand
In CASE 2 why did we end up with the
vendorsbundle containing both the common code (jquery) and whatever remained from thevendorsentry (some_jquery_plugin)? From my understanding, what theCommonsChunkPlugindid here was that it gathered the common code (jquery), and since we forced it to output it to thevendorsbundle, it kind of "merged" the common code into thevendorsbundle (which now only contained the code fromsome_jquery_plugin). Please confirm or explain.In CASE 3 I do not understand what happened when we passed
{ names : ['vendors', 'manifest'] }to the plugin. Why/how was thevendorsbundle kept intact, containing bothjqueryandsome_jquery_plugin, whenjqueryis clearly a common dependency, and why was the generatedmanifest.bundle.jsfile created the way it was created (requiring all other bundles and containing the runtime) ?
回答1:
This is how the CommonsChunkPlugin works.
A common chunk "receives" the modules shared by several entry chunks. A good example of a complex configuration can be found in the Webpack repository.
The CommonsChunkPlugin is run during the optimization phase of Webpack, which means that it operates in memory, just before the chunks are sealed and written to the disk.
When several common chunks are defined, they are processed in order. In your case 3, it is like running the plugin twice. But please note that the CommonsChunkPlugin can have a more complex configuration (minSize, minChunks, etc) that impacts the way modules are moved.
CASE 1:
- There are 3
entrychunks (entry1,entry2andvendors). - The configuration sets the
commonschunk as a common chunk. - The plugin processes the
commonscommon chunk (since the chunk does not exist, it is created):- It collects the modules that are used more than once in the other chunks:
entry1,entry2andvendorsusejqueryso the module is removed from these chunks and is added to thecommonschunk. - The
commonschunk is flagged as anentrychunk while theentry1,entry2andvendorschunks are unflagged asentry.
- It collects the modules that are used more than once in the other chunks:
- Finally, since the
commonschunk is anentrychunk it contains the runtime and thejquerymodule.
CASE 2:
- There are 3
entrychunks (entry1,entry2andvendors). - The configuration sets the
vendorschunk as a common chunk. - The plugin processes the
vendorscommon chunk:- It collects the modules that are used more than once in the other chunks:
entry1andentry2usejqueryso the module is removed from these chunks (note that it is not added to thevendorschunk because thevendorschunk already contains it). - The
vendorschunk is flagged as anentrychunk while theentry1andentry2chunks are unflagged asentry.
- It collects the modules that are used more than once in the other chunks:
- Finally, since the
vendorschunk is anentrychunk, it contains the runtime and thejquery/jquery_pluginmodules.
CASE 3:
- There are 3
entrychunks (entry1,entry2andvendors). - The configuration sets the
vendorschunk and themanifestchunk as common chunks. - The plugin creates the
manifestchunk as it does not exist. - The plugin processes the
vendorscommon chunk:- It collects the modules that are used more than once in the other chunks:
entry1andentry2usejqueryso the module is removed from these chunks (note that it is not added to thevendorschunk because thevendorschunk already contains it). - The
vendorschunk is flagged as anentrychunk while theentry1andentry2chunks are unflagged asentry.
- It collects the modules that are used more than once in the other chunks:
- The plugin processes the
manifestcommon chunk (since the chunk does not exist, it is created):- It collects the modules that are used more than once in the other chunks: as there are no modules used more than once, no module is moved.
- The
manifestchunk is flagged asentrychunk while theentry1,entry2andvendorsare unflagged asentry.
- Finally, since the
manifestchunk is anentrychunk it contains the runtime.
Hope it helps.
来源:https://stackoverflow.com/questions/39548175/can-someone-explain-webpacks-commonschunkplugin