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'
}
...
CommonsChunkPlugin
I will end up with 3 new bundle files:
entry1.bundle.js
which contains the complete code from entry1.js
and jquery
and contains its own runtimeentry2.bundle.js
which contains the complete code from entry2.js
and jquery
and contains its own runtimevendors.bundle.js
which contains the complete code from jquery
and some_jquery_plugin
and contains its own runtimeThis is obviously bad because I will potentially load jquery
3 times in the page, so we don't want that.
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.js
which contains the complete code from entry1.js
, a requirement for jquery
and does not contain the runtimeentry2.bundle.js
which contains the complete code from entry2.js
, a requirement for jquery
and does not contain the runtimevendors.bundle.js
which contains the complete code from some_jquery_plugin
, a requirement for jquery
and does not contain the runtimecommons.bundle.js
which contains the complete code from jquery
and contains the runtimeThis way we end up with some smaller bundles overall and the runtime is contained in the commons
bundle. Pretty ok but not ideal.
CASE 2 : If I pass { name : 'vendors' }
I will end up with the following bundle files:
entry1.bundle.js
which contains the complete code from entry1.js
, a requirement for jquery
and does not contain the runtimeentry2.bundle.js
which contains the complete code from entry2.js
, a requirement for jquery
and does not contain the runtimevendors.bundle.js
which contains the complete code from jquery
and some_jquery_plugin
and contains the runtime. This way, again, we end up with some smaller bundles overall but the runtime is now contained in the vendors
bundle. It's a little worse than the previous case, since the runtime is now in the vendors
bundle.
CASE 3 : If I pass { names : ['vendors', 'manifest'] }
I will end up with the following bundle files:
entry1.bundle.js
which contains the complete code from entry1.js
, a requirement for jquery
and does not contain the runtimeentry2.bundle.js
which contains the complete code from entry2.js
, a requirement for jquery
and does not contain the runtimevendors.bundle.js
which contains the complete code from jquery
and some_jquery_plugin
and does not contain the runtimemanifest.bundle.js
which contains requirements for every other bundle and contains the runtimeThis way we end up with some smaller bundles overall and the runtime is contained in the manifest
bundle. This is the ideal case.
In CASE 2 why did we end up with the vendors
bundle containing both the common code (jquery
) and whatever remained from the vendors
entry (some_jquery_plugin
)? From my understanding, what the CommonsChunkPlugin
did here was that it gathered the common code (jquery
), and since we forced it to output it to the vendors
bundle, it kind of "merged" the common code into the vendors
bundle (which now only contained the code from some_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 the vendors
bundle kept intact, containing both jquery
and some_jquery_plugin
, when jquery
is clearly a common dependency, and why was the generated manifest.bundle.js
file created the way it was created (requiring all other bundles and containing the runtime) ?
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:
entry
chunks (entry1
, entry2
and vendors
).commons
chunk as a common chunk.commons
common chunk (since the chunk does not exist, it is created):
entry1
, entry2
and vendors
use jquery
so the module is removed from these chunks and is added to the commons
chunk.commons
chunk is flagged as an entry
chunk while the entry1
, entry2
and vendors
chunks are unflagged as entry
.commons
chunk is an entry
chunk it contains the runtime and the jquery
module.CASE 2:
entry
chunks (entry1
, entry2
and vendors
).vendors
chunk as a common chunk.vendors
common chunk:
entry1
and entry2
use jquery
so the module is removed from these chunks (note that it is not added to the vendors
chunk because the vendors
chunk already contains it).vendors
chunk is flagged as an entry
chunk while the entry1
and entry2
chunks are unflagged as entry
.vendors
chunk is an entry
chunk, it contains the runtime and the jquery
/jquery_plugin
modules.CASE 3:
entry
chunks (entry1
, entry2
and vendors
).vendors
chunk and the manifest
chunk as common chunks.manifest
chunk as it does not exist.vendors
common chunk:
entry1
and entry2
use jquery
so the module is removed from these chunks (note that it is not added to the vendors
chunk because the vendors
chunk already contains it).vendors
chunk is flagged as an entry
chunk while the entry1
and entry2
chunks are unflagged as entry
.manifest
common chunk (since the chunk does not exist, it is created):
manifest
chunk is flagged as entry
chunk while the entry1
, entry2
and vendors
are unflagged as entry
.manifest
chunk is an entry
chunk it contains the runtime.