gwt代码拆分:测试片段是否已经加载有什么好处吗?

gwt code splitting: is there any benefit in testing whether fragment already loaded or not?

GWT Code Splitting Dev Guide 的上下文和其中定义排除代码片段的建议模块模式中,我了解到第一次调用静态 Module.createAsync(final ModuleClient client) 然后 [=12] 中的代码=] class 已下载,后续调用此静态函数将不会再次下载相同的代码片段。

该模式进一步建议为 "for any code that definitely loads after the module".

缓存 Module class 的 INSTANCE

所以我的问题是:

  1. 初始片段第一次调用后,是否每次调用Module.createAsync(final ModuleClient client)都会调用服务器检查是否需要下载代码片段?还是在没有任何服务器调用开销的情况下调用 onSuccess()

  2. 初始片段中的以下代码是否会导致 Module 代码成为初始下载的一部分(即,不是排除片段)?

>

if (INSTANCE == null)
  Module.createAsync(new ModuleClient()
  {
    @Override
    public void onUnavailable(Throwable reason)
    {
      // Action in case of failure
    }
    @Override
    public void onSuccess(Module instance)
    {
      instance.showBigComplicatedStuff();
    }
  });
else
  INSTANCE.showBigComplicatedStuff();

换句话说:

  1. 初始片段子句中 INSTANCE.showBigComplicatedStuff(); 的存在是否导致包含 showBigComplicatedStuff()Module 代码成为初始片段的一部分还是 Module 无论如何都会在独占片段中,因为 new Module()Module.createAsync 内调用(即在 GWT.runAsync 内)?

  2. 这种仅在 INSTANCE == null 时才第一次调用 Module.createAsync 的模式是否有助于减少对服务器的不必要的异步调用? (同样,我知道那些最终的服务器调用不会再次下载相应的 Module 片段)。

您的代码不完整 - 为什么您有 INSTANCEinstance 并不明显,如果 INSTANCE 是作为 [=61] 的一部分生成的 public 字段=],还有什么可以填充它吗?我将尝试自己回答这两个问题,并指出我在此过程中所做的任何假设

  1. 假设永远不可能在 GWT.runAsync 之外创建 INSTANCE 类型的 objects,实例方法 showBigComplicatedStuff 不能做任何事情,除非那个分割点有已加载(因此至少创建了一个实例)——编译器足够聪明,可以解决这个问题。然而,

  2. 空检查毫无意义,正是因为你提到的原因 - 如果你明白没有服务器调用去获取新的 GWT.runAsync 片段,那么异步服务器调用什么你认为 GWT.runAsync 里面发生了什么?如果代码已经下载了,不需要再次下载,那就没有什么可下载的了。

页面加载后第二次 运行 和 GWT.runAsync 没有开销。如果缓存实现正确,即使在页面加载后第一次点击再次应该是cheap/free(意味着服务器不会再次被点击,但是有仍然是将 JS 解析到内存中的开销。

因此,由于 GWT.runAsync 在加载后没有服务器调用开销(因此 INSTANCE 是非 null),您不必担心它。 GWT 会注意到它已经拥有所需的代码,并且不会尝试再次下载它。


即使没有 so-called 'perfect' 缓存,这个行为也会成立。如果你碰巧设置了缓存 headers 以便你的 <hashname>.cache.* 文件被缓存一年,那么第二次加载模块或分割点时,它将继续使用相同的本地结果没有网络流量。如果没有完美的缓存但文件在磁盘上仍然相同,则重新加载应用程序将导致 304 Not Modified - 不是免费的,但不像再次下载那么昂贵。

GWT 应用程序(使用标准链接器之一)以 appname.nocache.js 文件开始 - 此文件包含上面提到的 <hashname> 字符串,这些字符串仅在代码更改时更改,因此不得缓存以便可以发生代码更改,客户端会立即看到更改。给定属性集的初始片段(即 'which browser' * 'which locale' * 'which form factor' 等)然后作为 <hashname>.cache.js 从缓存中下载或读取,然后当给定的分割点 <N> 被击中,分割点被提取为 deferredjs/<hashname>/<N>.cache.js


综上所述,Module.createAsync 背后的理论是成为一个异步工厂,因此您当然可以按照您描述的方式使用它。在这种情况下,尽管只有一个实例很重要,但我可能有一个 getOrCreateAsync 来执行模块 class 中的单例位 - 只要 class 负责创建实例并提供它,它还不如总是提供它。这实际上取决于您如何使用实例、它包含的内容等。