我在GWT中使用代码拆分来减少初始JavaScript的大小。 当我的应用程序初始化时,我想预取我的代码中的其他(更大)部分,如文档(www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html)中所述。
private void doSth(final boolean prefetch) {
GWT.runAsync(new RunAsyncCallback() {
public void onFailure(Throwable caught) {
Log.error("Loading the code failed!");
}
public void onSuccess() {
if(prefetch)
return; //do nothing. just a prefetch
//here is the loaded code
}
});
}
但我无法承认性能的提升。在我分析浏览器日志时,我发现,加载JavaScript的请求未标记为XHR。 GWT是否同步加载分裂点的代码?
答案 0 :(得分:4)
性能改进在初始下载的代码中,假设没有其他代码引用该代码。如果//here is the loaded code
的工作还有其他功能,那么很少或根本没有代码可以分解为单独下载的JS文件。
可以通过多种方式禁用此功能,包括使用开发模式或设置编译器标志以跳过此过程。在这种情况下,是的,分裂点同步运行,因为等待是没有意义的。此外,在文件加载一次后,下次在同一页面加载中调用代码时不需要加载它。
如果您的服务器设置为正确缓存,那么在第一次访问之后,由于无需下载,因此节省的成本更低 - 您只需节省将该代码解析到浏览器的JS VM所需的时间。
但除此之外,我们还需要更多信息。
这是一个快速演示,演示了如何使用更多内容编写分割点,并让您使用浏览器注意分割点代码是如何单独引入的。
public class SampleEntryPoint implements EntryPoint {
public void onModuleLoad() {
Label label = new Label("Hello, World!");
label.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
GWT.runAsync(new RunAsyncCallback() {
public void onFailure(Throwable var1) {/*ignore*/}
public void onSuccess() {
Window.alert("Clicked, and loaded in split point!");
}
});
}
});
RootPanel.get().add(label);
}
}
独立样本: https://viola.colinalworth.com:444/compiled/755e224e7f48a047703d44eb6903f76c/
当您加载此页面时,nocache
文件会加载,初始下载也会加载(通过Chrome浏览器的“检查程序”网络标签):
然后,当您单击Label小部件时,onClick会触发runAsync并下载额外的分割点(加上"剩余的"片段):
将这两个新条目添加到“网络”标签后,您会看到显示警告消息。后续点击不会导致这种轻微的延迟,也不会强迫这个额外的JS再次下载。
另请注意,这些不会作为AJAX / XHR调用加载,而是作为要添加到页面的脚本标记加载。单击Initiator列中的详细信息(未显示)会导致此(格式化以便于阅读):
function fb(a) {
var b, c, d;
d = (bb(), window);
b = d.document;
c = b.createElement('script');
(!!a.a || a.b) && cb(c, a.a, a.b);
eb(c, a.c);
(b.head || b.getElementsByTagName('head')[0]).appendChild(c);
return c
}
通过混淆代码,我们发现创建了<script>
标记,并将其附加到页面的<head>
。
深入挖掘,我们可以发现AsyncFragmentLoader.LoadingStrategy
界面描述了如何获取此片段,com/google/gwt/core/AsyncFragmentLoader.gwt.xml
默认将此线连接到XhrLoadingStrategy
。但是,xs
和xsiframe
链接器都会将其更改为CrossSiteLoadingStrategy
和ScriptTagLoadingStrategy
。至于GWT的最新版本(您没有指定,所以我假设您使用的是最新版本),xsiframe
链接器是默认的。来自Core.gwt.xml:
<add-linker name="xsiframe" />
我们可以通过切换到旧链接器来定制它,或者只是替换策略。请注意,切换XHR策略将阻止跨域加载正常工作(例如SuperDevMode),因此请小心。
就像AsyncFragmentLoader.gwt.xml
将接口连接到XhrLoadingStrategy
并且CrossSiteIframeLinker.gwt.xml
将其更改为ScriptTagLoadingStrategy
一样,我们可以将其更改回来。我们创建了一个用LoadingStrategy
替换XhrLoadingStrategy
的规则,并在我们的GWT继承.gwt.xml文件中的语句后列出它:
<replace-with class="com.google.gwt.core.client.impl.XhrLoadingStrategy">
<when-type-is class="com.google.gwt.core.client.impl.AsyncFragmentLoader.LoadingStrategy" />
</replace-with>
这是旧的默认值作为std
链接器(com.google.gwt.core.linker.IFrameLinker
)的一部分所依赖的内容,但不再鼓励这种情况,可能会在以后的版本中删除。