Can someone explain Webpack CommonsChunkPlugin

I get the general meaning that CommonsChunkPlugin looks at all entry points, checks to see if there are common packages / dependencies between them, and splits them into its own package.

So let's say 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 contact without using CommonsChunkPlugin

As a result, I will have 3 new package files:

  • entry1.bundle.js , which contains the complete code from entry1.js and jquery and contains its own runtime
  • entry2.bundle.js , which contains the complete code from entry2.js and jquery and contains its own runtime
  • vendors.bundle.js which contains the complete code from jquery and some_jquery_plugin and contains its own runtime

This is obviously bad because I will potentially load jquery 3 times per page, so we donโ€™t want this.

If I contact using CommonsChunkPlugin

Depending on which arguments are passed to CommonsChunkPlugin , the following will happen:

  • CASE 1: If I pass { name : 'commons' } , I will have the following package files:

    • entry1.bundle.js , which contains the complete code from entry1.js , is a requirement for jquery and does not contain runtime
    • entry2.bundle.js , which contains the complete code from entry2.js , is a requirement for jquery and does not contain runtime
    • vendors.bundle.js , which contains the complete code from some_jquery_plugin , is a requirement for jquery and does not contain runtime
    • commons.bundle.js which contains the full code from jquery and contains runtime

    This way we get a few small packages in general, and the runtime is contained in the commons package. Pretty normal, but not perfect.

  • CASE 2: If I go through { name : 'vendors' } , I will have the following package files:

    • entry1.bundle.js , which contains the complete code from entry1.js , is a requirement for jquery and does not contain runtime
    • entry2.bundle.js , which contains the complete code from entry2.js , is a requirement for jquery and does not contain runtime
    • vendors.bundle.js , which contains the complete code from jquery and some_jquery_plugin and contains runtime.

    Thus, we again receive several small packages, but the runtime is now contained in the vendors package. This is slightly worse than in the previous case, since the runtime is now in the vendors package.

  • CASE 3: If I go through { names : ['vendors', 'manifest'] } , I will have the following package files:

    • entry1.bundle.js , which contains the complete code from entry1.js , is a requirement for jquery and does not contain runtime
    • entry2.bundle.js , which contains the complete code from entry2.js , is a requirement for jquery and does not contain runtime
    • vendors.bundle.js , which contains the complete code from jquery and some_jquery_plugin and does not contain a runtime
    • manifest.bundle.js , which contains requirements for every other package and contains runtime

    Thus, we end up with small packages in general, and the runtime is contained in the manifest package. This is an ideal case.

What I don't understand / I'm not sure I understand

  • In CASE 2, why did we end up with a vendors package containing both generic code ( jquery ) and all that remains of the vendors ( some_jquery_plugin )? In my opinion, the CommonsChunkPlugin here was that it compiled the generic code ( jquery ), and since we forced it to output it to the vendors package, it kind of โ€œcombinedโ€ the generic code into the vendors bundle (which now only contains code from some_jquery_plugin ) Please confirm or explain.

  • In CASE 3, I donโ€™t understand what happened when we passed { names : ['vendors', 'manifest'] } plugin. Why / how the vendors package vendors kept intact, containing both jquery and some_jquery_plugin , when jquery clearly a common dependency, and why the generated manifest.bundle.js file was created the way it was created (requiring all other packages and containing runtime) ?

+59
javascript webpack bundle webpack-plugin commonschunkplugin
Sep 17 '16 at
source share
1 answer

This is how CommonsChunkPlugin works.

A common chunk "receives" modules shared by several input blocks. A good example of complex configuration can be found in the Webpack repository .

CommonsChunkPlugin runs during the Webpack optimization phase, which means that it runs in memory shortly before the pieces are sealed and written to disk.

When several common pieces are defined, they are processed in order. In your case 3, this is like running the plugin twice. But CommonsChunkPlugin that CommonsChunkPlugin may have a more complex configuration (minSize, minChunks, etc.), which affects the movement of modules.

CASE 1:

  • There are 3 entry pieces ( entry1 , entry2 and vendors ).
  • The configuration sets the commons block as a common fragment.
  • The plugin processes the common commons fragment (since the piece does not exist, it is created):
    • It collects modules that are used more than once in other fragments: entry1 , entry2 and vendors use jquery , so the module is removed from these fragments and added to the commons block.
    • The commons block is marked as an entry fragment, while the entry1 , entry2 and vendors not marked as entry .
  • Finally, since the commons block is an entry block, it contains a runtime module and jquery .

CASE 2:

  • There are 3 entry pieces ( entry1 , entry2 and vendors ).
  • The configuration sets the vendors block as a common fragment.
  • The plugin handles the generic vendors :
    • It collects modules that are used more than once in other fragments: entry1 and entry2 use jquery , so the module is removed from these fragments (note that it is not added to the vendors block because the vendors already contains it).
    • The vendors block vendors marked as an entry fragment, while the entry1 and entry2 not marked as entry .
  • Finally, since the vendors block is an entry block, it contains runtime modules and jquery / jquery_plugin .

CASE 3:

  • There are 3 entry pieces ( entry1 , entry2 and vendors ).
  • The configuration sets the vendors and the manifest fragment as normal chunks.
  • The plugin creates a piece of manifest because it does not exist.
  • The plugin handles the generic vendors :
    • It collects modules that are used more than once in other fragments: entry1 and entry2 use jquery , so the module is removed from these fragments (note that it is not added to the vendors block because the vendors already contains it).
    • The vendors block vendors marked as an entry fragment, while the entry1 and entry2 not marked as entry .
  • The plugin processes the general manifest chunk (since the chunk does not exist, it is created):
    • It collects modules that are used more than once in other pieces: since there are no modules used more than once, the module does not move.
    • The manifest block is marked as entry chunk, and entry1 , entry2 and vendors not marked as entry .
  • Finally, since the manifest chunk is an entry fragment, it contains the runtime.

Hope this helps.

+76
Sep 20 '16 at 17:58
source share



All Articles