Webpack 2 - 代码拆分顶级依赖项 [英] Webpack 2 - Code splitting top-level dependencies

查看:43
本文介绍了Webpack 2 - 代码拆分顶级依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最终编辑

tl;dr 的解决办法是,这是不可能的.虽然下面的最佳答案确实有一些很好的信息.

考虑下面来自 contacts.js 的代码.这是一个动态加载的模块,在代码的其他地方使用 System.import 按需加载.

Consider the code below, from contacts.js. This is a dynamically loaded module, loaded on demand with System.import elsewhere in the code.

如果 SharedUtil1 也用于其他模块 动态加载 System.import,我将如何使用 SharedUtility1 所有这些模块中排除,并且仅在第一次需要时按需加载?

If SharedUtil1 is also used in other modules which are also dynamically loaded with System.import, how would I go about having SharedUtility1 excluded from all of these modules, and only loaded on demand the first time it's needed?

SharedUtil1 的顶级 System.import 不起作用,因为我的导出依赖于它:导出只能放置在模块的顶级代码,而不是任何类型的回调.

A top-level System.import of SharedUtil1 won't work, since my export depends on it: exports can only be placed in the top level of a module's code, not in any sort of callback.

这可以用 Webpack 实现吗?我使用的是 2.0.7 测试版.

Is this possible with Webpack? I'm on version 2.0.7 beta.

import SharedUtil1 from '../../SharedUtilities/SharedUtility1';

class Contacts{
    constructor(data){
        this.data = data;
        this.sharedUtil1 = new SharedUtil1();
    }
}

export default Contacts;

<小时>

更新 1

我认为 bundle loader 是我想要的,但不,这会改变您导入的模块进入一个不同的函数,一旦它完成异步加载,你就可以通过回调调用该函数以访问实际模块.这意味着您不能透明地使模块 X 异步加载而不对代码进行重大更改,更不用说您回到最初描述的问题的事实,即如果您的顶级模块依赖于 now-asynchronously加载依赖项,无法导出它,因为导出必须位于顶层.

I thought the bundle loader was what I wanted, but no, that turns your imported module into a different function that you call with a callback to get to the actual module, once it's done loading asynchronously. This means you can't transparently make module X load asynchronously without making breaking changes to your code, to say nothing of the fact that you're back to the problem originally described, that if your top-level module depends on the now-asynchronously loaded dependency, there's no way to export it, since exports must be at the top level.

Webpack 中是否没有办法表明依赖项 X 将按需加载,如果需要,并且有任何导入它的导入模块以透明地等待导入过程?我认为这个用例对于任何远程大型应用程序来说都是一个必要条件,所以我不得不认为我只是遗漏了一些东西.

Is there no way in Webpack to denote that dependency X is to be loaded on-demand, if needed, and have any imported modules which import it to transparently wait out the importation process? I would think this use case would be a sine qua non for any remotely large application, so I have to think I'm just missing something.

更新 2

根据 Peter 的回答,我试图让重复数据删除工作,因为 commonChunk 插件涉及在端点之间共享代码,正如他所提到的,并且由于 require.ensure 将加载的代码放入回调中,从而阻止您在 ES6 export 任何依赖于它的代码.

Per Peter's answer, I attempted to get deduplication working, since the commonChunk plugin relates to sharing code between end points, as he mentioned, and since require.ensure places the loaded code into a callback, thereby preventing you from ES6 exporting any code that depends on it.

就重复数据删除而言,contacts.jstasks.js 都像这样加载相同的 sharedUtil

As far as deduplication, contacts.js and tasks.js both load the same sharedUtil like so

从'../../sharedUtilities/sharedUtility1'导入SharedUtil1;

我尝试将 webpack 作为

I tried running webpack as

webpack --optimize-dedupe

也可以通过添加

plugins: [
    new webpack.optimize.DedupePlugin()
]

到 webpack.config.在这两种情况下,sharedUtil 代码仍然放置在联系人和任务包中.

to webpack.config. In both cases though the sharedUtil code is still placed in both the contacts and tasks bundles.

推荐答案

阅读您的博文后,我终于明白您的意图了.顶级依赖"这个词让我有点困惑.

After reading your blog post I finally understand what you intended. I got a bit confused by the word "Top-level dependencies".

您有两个模块(async-aasync-b),它们可以从任何地方按需加载(这里是一个模块 main) 并且两者都有一个共享模块的引用 (shared).

You have two modules (async-a and async-b) which are loaded on-demand from anywhere (here a module main) and both have a reference on a shared module (shared).

- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)

main - - -> async-a ---> shared
main - - -> async-b ---> shared

默认情况下,webpack 创建一个像这样的块树:

By default webpack creates a chunk tree like this:

---> chunk uses other chunk (child-parent-relationship)

entry chunk [main] ---> on-demand chunk 1 [async-a, shared]
entry chunk [main] ---> on-demand chunk 2 [async-b, shared]

这在 shared 时很好async-a/basync-aasync-b 被同一用户同时使用的概率很低.这是默认设置,因为它是最简单的行为,并且可能是您所期望的:一个 System.import => 一个块.在我看来,这也是最常见的情况.

This is fine when shared < async-a/b or the probability that async-a and async-b are used both by the same user is low. It's the default because it's the simplest behaviors and probably what you would expect: one System.import => one chunk. In my opinion it's also the most common case.

但是如果 shared >= async-a/b 并且 async-aasync-b被用户加载高,有一个更有效的分块选项:(有点难以想象):

But if shared >= async-a/b and the probability that async-a and async-b is loaded by the user is high, there is a more efficient chunking option: (a bit difficult to visualize):

entry chunk [main] ---> on-demand chunk 1 [async-a]
entry chunk [main] ---> on-demand chunk 2 [async-b]
entry chunk [main] ---> on-demand chunk 3 [shared]

When main requests async-a: chunk 1 and 3 is loaded in parallel
When main requests async-b: chunk 2 and 3 is loaded in parallel
(chunks are only loaded if not already loaded)

这不是默认行为,但有一个插件可以将其存档:异步模式下的 CommonChunkPlugin.它在一堆块中找到公共/共享模块,并创建一个包含共享模块的新块.在异步模式下,它确实与原始(但现在较小)块并行加载新块.

This is not the default behavior, but there is a plugin to archive it: The CommonChunkPlugin in async mode. It find the common/shared modules in a bunch of chunks and creates a new chunks which includes the shared modules. In async mode it does load the new chunk in parallel to the original (but now smaller) chunks.

new CommonsChunkPlugin({
    async: true
})

// This does: (pseudo code)
foreach chunk in application.chunks
  var shared = getSharedModules(chunks: chunk.children, options)
  if shared.length > 0
    var commonsChunk = new Chunk(modules: shared, parent: chunk)
    foreach child in chunk.children where child.containsAny(shared)
      child.removeAll(shared)
      foreach dependency in chunk.getAsyncDepenendenciesTo(child)
        dependeny.addChunk(commonsChunk)

请记住,CommonsChunkPlugin 有一个 minChunks 选项来定义模块何时被线程化为 shared(随意提供一个自定义函数来选择模块).

Keep in mind that the CommonsChunkPlugin has a minChunks option to define when a module is threaded as shared (feel free to provide a custom function to select the modules).

这是一个详细解释设置和输出的示例:https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk

Here is an example which explains the setup and output in detail: https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk

另一个配置更多的:https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced

这篇关于Webpack 2 - 代码拆分顶级依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆