(Webpack) 如何分块动态模块依赖

(Webpack) How to chunk dynamic module dependencies

我刚刚意识到,如果您使用 require.ensure() 动态加载模块,webpack 将不会分析依赖关系并将其分块在一起。这在某种程度上是有道理的,有人可能会争辩说,webpack 不知道这些模块是否被传输过,但我们能强制 webpack 完成这项工作吗?

例子是:

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' );

这个编译的结果是,这两个模块都将整个 socket-io 库 "linked" 放入它们的块中。我最初的期望是,CommonsChunkPlugin 将捕获那些 requires 并将那个大库放入一个公共块中。

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

但是不起作用。当然,我总是可以手动 "resolve" 这个依赖项,但我希望 webpack 能以某种方式解决这个问题?

到目前为止,我找到了一种可能的解决方案。 如果您使用 webpack 的 require.include() 方法仅包含(不评估)“共享库,此处socket.io-client”也在父模块中,这里app.jsCommonChunkPlugin现在可以正确地解决问题。

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');

但是,这对我来说似乎不正确,因为这是手动解决依赖关系,这实际上不是我想要使用 Webpack 之类的东西必须要做的事情。

答案隐藏在 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是这个配置的主要部分。 来自文档:

If true all children of the commons chunk are selected


编辑异步公共块

如果你想异步下载块中的通用代码,你应该改变上面的配置添加async: true

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

来自关于 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.

现在创建了仅包含示例中的 socket.io-client 的附加块。 这接近 webpack docs.

中的原始示例