Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Webpack) How to chunk dynamic module dependencies

I just realized that if you load modules dynamically using require.ensure(), webpack will not analyze and chunk dependencies together. This makes sense in some way that one could argue, that webpack can't know if such modules are transferred ever, but can we force webpack to do the job anyway?

Example is:

app.js:

require.ensure([ 'module1.js' ], ( require ) => {
    // at some point
    require( 'module1.js' );
}, 'Module1');

require.ensure([ 'module2.js' ], ( require ) => {
    // at some point
    require( 'module2.js' );
}, 'Module2');

module1.js

let io = require( 'socket.io-client' );

module2.js

let io = require( 'socket.io-client' );

The outcome of this compilation is, that both of these modules get the whole socket-io library "linked" into their chunks. My original expectation was, that the CommonsChunkPlugin will catch those requires and put that big library into a common chunk.

new webpack.optimize.CommonsChunkPlugin( 'common' ),

Doesn't work however. Of course I could always "resolve" this dependency manually, but I hoped that webpack can do the trick somehow?

like image 679
jAndy Avatar asked Sep 01 '16 12:09

jAndy


1 Answers

Answer is hidden in configuration of CommonsChunkPlugin

new webpack.optimize.CommonsChunkPlugin({
  name: 'main', // Important to use 'main' or not specify, since 'main' is default
  children: true, // Look for common dependencies in all children,
  minChunks: 2, // How many times a dependency must come up before being extracted
});

children: true is the main part of this configuration. From docs:

If true all children of the commons chunk are selected


Edit for async common chunk

If you want to download asynchronously common code in chunk, you should change above configuration with addition of async: true

new webpack.optimize.CommonsChunkPlugin({
  name: 'main',
  children: true, 
  minChunks: 2, 
  async: true, // modification
});

From docs about async:

If true a new async commons chunk is created as child of options.name and sibling of options.chunks. It is loaded in parallel with options.chunks. It is possible to change the name of the output file by providing the desired string instead of true.

Now there is created additional chunk containing only socket.io-client from your example. This is close to original example in webpack docs.

like image 80
Everettss Avatar answered Sep 30 '22 15:09

Everettss