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?
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
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.