简体   繁体   中英

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

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 .

So far I found one possible solution. If you use webpack's require.include() method to just include (not evaluate) the " shared library , here socket.io-client " also in the parent module, here app.js , the CommonChunkPlugin will now be able to sort things out correctly.

require.include( 'socket.io-client' ); // import io from 'socket.io-client'; also works
require.ensure([ 'module1.js' ], ( require ) => {
    // at some point
    require( 'module1.js' );
}, 'Module1');

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

However, this doesn't seem right to me since this IS a manual resolving of dependencies, which is actually not what I want have to do using something like Webpack .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM