GWT编译器会因代码拆分而产生代码片段(请参阅详细信息here)
初始下载文件在下图中以{alphanumeric} .cache.js(例如1805B2053A824F148DB6D05B2186F955.cache.js)和其他片段{number} .cache.js(例如1.cache.js)命名。
我正在尝试使用Service Worker开发GWT应用程序,因为我希望应用程序脱机工作。缓存和脱机后,初始下载文件的GET请求会触发ServiceWorker中的FETCH事件,但单个代码片段不会触发该事件。出于某种原因,他们似乎绕过了服务工作者。
要进行演示,请检查https://gwt-pwa-demo.herokuapp.com/pwademo.html处的应用。它是一个使用Service Worker的GWT应用程序。它不是我的应用程序,我只是用它来进行演示。
加载应用时,所有文件都会被缓存。不要从chrome dev工具离线,并刷新应用程序。该应用程序仍然显示,您将注意到初始下载文件是从Service Worker加载的。现在点击,巴黎/柏林/伦敦,它将加载片段1.cache.js,依此类推。请注意,这些来自磁盘缓存而不是来自ServiceWorker的缓存。如果查看控制台输出,则无法查看从ServiceWorker Fetch事件打印的这些片段的日志。
为了澄清更多,该应用程序只能脱机工作,因为片段是从磁盘缓存中提取的。如果磁盘缓存中不存在这些片段,则该应用程序无法正常工作。即使片段存在于缓存存储中,由于ServiceWorker无法拦截这些请求,因此它们不会被加载。请按照以下步骤查看此操作。
答案 0 :(得分:1)
好的,我想我发现了@ https://bugs.chromium.org/p/chromium/issues/detail?id=439697的铬虫报告和相关的ServiceWorker规范问题@ https://github.com/w3c/ServiceWorker/issues/612。
GWT通过在内部创建iframe来加载代码片段。这些iframe不受父母服务工作者的控制。 Chrome bug仍处于打开状态,但是w3c关闭了规范问题@ https://github.com/w3c/ServiceWorker/issues/1163。
答案 1 :(得分:0)
您必须使用xhr请求加载片段。
1)首先,您必须扩展CrossSiteFrameLinker
/**
* Created by Gernot Pansy <gernot.pansy@ut11.net> on 07.08.17.
*/
@LinkerOrder(LinkerOrder.Order.PRIMARY)
@Shardable
public class ProgressiveWebAppLinker extends CrossSiteIframeLinker {
@Override
public String getDescription() {
return "Progressive-Web-App";
}
@Override
protected String wrapDeferredFragment(final TreeLogger logger, final LinkerContext context, final int fragment,
final String js, final ArtifactSet artifacts) {
return js;
}
@Override
protected String getJsInstallLocation(final LinkerContext context) {
return "com/google/gwt/core/ext/linker/impl/installLocationMainWindow.js";
}
@Override
protected String wrapPrimaryFragment(final TreeLogger logger, final LinkerContext context, final String script,
final ArtifactSet artifacts, final CompilationResult result)
throws UnableToCompleteException {
return script;
}
@Override
protected String getJsInstallScript(final LinkerContext context) {
return "xxxxxxx/progressiveWebAppInstallScript.js";
}
@Override
protected String getJsIsBodyLoaded(final LinkerContext context) {
return "";
}
@Override
protected String getJsWaitForBodyLoaded(final LinkerContext context) {
return "";
}
@Override
protected String getScriptChunkSeparator(TreeLogger logger, LinkerContext context) {
return "";
}
@Override
protected boolean shouldInstallCode(final LinkerContext context) {
return true;
}
}
2)您需要修改后的javascript安装脚本(progressiveWebAppInstallScript.js):
function installScript(filename) {
function installCode(code) {
function removeScript(body, element) {
// Unless we're in pretty mode, remove the tags to shrink the DOM a little.
// It should have installed its code immediately after being added.
__START_OBFUSCATED_ONLY__
body.removeChild(element);
__END_OBFUSCATED_ONLY__
}
var doc = getInstallLocationDoc();
var script = doc.createElement('script');
script.language='javascript';
script.text = code;
doc.body.appendChild(script);
removeScript(doc.body, script);
}
sendStats('moduleStartup', 'moduleRequested');
var xhr = new $wnd.XMLHttpRequest()
xhr.open("GET", filename);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// Clearing onreadystatechange otherwise it may cause memory leak (e.g. in IE8).
xhr.onreadystatechange = function() {}; // Clear callback
if (xhr.status == 200) {
installCode(xhr.responseText);
} else if (__MODULE_FUNC__.__errFn) {
__MODULE_FUNC__.__errFn('__MODULE_FUNC__', new Error("Failed to load " + code));
}
}
};
xhr.send(null);
}