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

Posted

技术标签:

【中文标题】(Webpack) 如何分块动态模块依赖【英文标题】:(Webpack) How to chunk dynamic module dependencies 【发布时间】:2017-01-09 09:04:34 【问题描述】:

我刚刚意识到,如果你使用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 库“链接”到它们的块中。我最初的期望是,CommonsChunkPlugin 会捕获那些 requires 并将那个大库放入一个公共块中。

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

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

【问题讨论】:

Doe 在CommonsChunkPlugin options 中将minChunks 设置为2 改变情况? 很遗憾没有。 【参考方案1】:

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

如果为 true,则公共块的所有子项都被选中


编辑异步公共块

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

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

来自关于async的文档:

如果为 true,则创建一个新的异步公共块作为 options.name 的子级 和 options.chunks 的兄弟姐妹。它与并行加载 选项.块。可以更改输出文件的名称 通过提供所需的字符串而不是 true。

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

【讨论】:

啊,我真希望就是这样,但事实证明,它在这种情况下无济于事。如果我打开children: true,所发生的一切就是我的“通用”块现在与main-bundle 链接在一起。但它不会影响动态加载的包。两者仍然将共享库/需要链接到他们的块中。 async: true 能完成这项工作吗? 没有区别。两个动态模块仍然链接到相同的 socket-io 库。我正在 webpack 2.1.0-beta.20 上进行所有测试,几乎是最新的。 哦,我展示了最新稳定版 v1.13.2 的答案 确实成功了。除了children: true,它还创建了预期的行为(将socket-io lib链接到主块)。我认为 name 属性 只是一些随机的 id 分别设置了输出文件名......现在谢谢,这也可能会获得赏金。【参考方案2】:

到目前为止,我找到了一种可能的解决方案。 如果您使用 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 之类的东西所做的事情。

【讨论】:

以上是关于(Webpack) 如何分块动态模块依赖的主要内容,如果未能解决你的问题,请参考以下文章

webpack

webpack

Webpack 和 AWS Lambda 问题 - 模块上缺少处理程序

前端模块化开发篇之grunt&webpack篇

vue中动态加载图片报错

如何找到具有特定依赖关系的 NPM 模块版本 - 例如,哪个版本的 webpack-cli 与 webpack@4.46.0 一起使用?