(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.js,CommonChunkPlugin 现在可以正确排序了。
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 和 AWS Lambda 问题 - 模块上缺少处理程序
如何找到具有特定依赖关系的 NPM 模块版本 - 例如,哪个版本的 webpack-cli 与 webpack@4.46.0 一起使用?