我查阅了很多有关 Service Workers 的资源:
- 更新您的 ServiceWorker https://jakearchibald.com/2014/using-serviceworker-today/#updating-your-serviceworker
- ServiceWorker:Web 平台的革命 https://ponyfoo.com/articles/serviceworker-revolution
- 杰克阿奇博尔德很可爱SVGOMG https://github.com/jakearchibald/svgomg/blob/6c21157b65dd779bbf2dd2adf9831aaf71d4bb08/src/js/sw/index.js.
但是,我一生都无法弄清楚如何在安装新的 ServiceWorker 后更新页面。无论我做什么,我的页面都停留在旧版本上,只有硬刷新(Cmd-Shift-R)才能修复它。不能同时使用 1) 关闭选项卡、2) 关闭 Chrome 或 3)location.reload(true)
将服务新内容。
我有一个超级简单的示例应用程序 https://github.com/nolanlawson/serviceworker-update-demo主要基于 SVGOMG。安装时,我使用缓存一堆资源cache.addAll()
,我也这样做skipWaiting()
如果当前版本的主版本号与活动版本号不匹配(基于 IndexedDB 查找):
self.addEventListener('install', function install(event) {
event.waitUntil((async () => {
var activeVersionPromise = localForage.getItem('active-version');
var cache = await caches.open('cache-' + version);
await cache.addAll(staticContent);
var activeVersion = await activeVersionPromise;
if (!activeVersion ||
semver.parse(activeVersion).major === semver.parse(version).major) {
if (self.skipWaiting) { // wrapping in an if while Chrome 40 is still around
self.skipWaiting();
}
}
})());
});
我正在使用受 semver 启发的系统,其中主版本号表明新的 ServiceWorker 无法热插拔为旧的 ServiceWorker。这适用于 ServiceWorker 端 - 从 v1.0.0 到 v1.0.1 的更新会导致工作线程在刷新时立即安装,而从 v1.0.0 到 v2.0.0,它会等待选项卡关闭并重新打开,然后再重新安装。安装。
回到主线程,我在注册后手动更新 ServiceWorker - 否则页面永远不会收到有新版本的 ServiceWorker 可用的备忘录(奇怪的是,我发现 ServiceWorker 文献中很少提到这一点):
navigator.serviceWorker.register('/sw-bundle.js', {
scope: './'
}).then(registration => {
if (typeof registration.update == 'function') {
registration.update();
}
});
但是,无论我将版本增加到 1.0.1 还是 2.0.0,提供给主线程的内容始终停留在旧版本的页面上(“我的版本是 1.0.0”)。
我有点困惑在这里。我希望找到一个优雅的 semver-y 解决方案来实现 ServiceWorker 版本控制(因此我使用require('./package.json').version
),但在我当前的实现中,用户永远停留在旧版本的页面上,除非他们硬刷新或手动清除所有数据。 :/