【发布时间】:2020-02-28 09:55:18
【问题描述】:
平台
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
工作箱版本
5.0.0-rc.0
我正在使用workbox-window update() 方法来触发服务工作者更新检查,如workbox issue #2130 中所述。这个问题似乎也与workbox issue #2301 中的观察有关。
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/5.0.0-rc.0/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
// Grab the update button from the UI using jQuery and add a listener to it.
$('#update-button').on('click', function () {
wb.update();
});
....
}
</script>
如果发现更新,则加载新的服务工作者并进入等待状态。我监听这个事件(waiting 和 externalwaiting,在这两种情况下都做同样的事情),并询问用户是现在还是以后安装更新。
function handleWaiting(wb) {
if (confirm("An update is available for this app. Install now?")) {
wb.messageSW({type: 'SKIP_WAITING'});
}
}
wb.addEventListener('waiting', event => {
handleWaiting(wb);
});
wb.addEventListener('externalwaiting', event => {
handleWaiting(wb);
});
大多数时候waiting 事件被触发,如果用户接受更新,Service Worker 被激活,我们可以重新加载页面以完成更新过程:
function handleActivated(wb, event) {
if (event.isUpdate) {
window.location.reload();
} else {
wb.messageSW({ type: 'CLIENTS_CLAIM' });
}
}
wb.addEventListener('activated', event => {
handleActivated(wb, event);
});
wb.addEventListener('externalactivated', event => {
handleActivated(wb, event);
});
如果waiting 事件被触发,这个过程可以正常工作。
- 对应用进行小幅更新,导致服务工作线程文件发生更改。
- 按“检查更新”按钮。
- 找到新的 service worker 并提示用户安装更新
- 页面已重新加载。
但如果externalwaiting 事件被触发,则此代码不起作用。新的 Service Worker 仍处于等待状态,我可以在 Chrome 开发工具中看到。
跳过旧服务人员收到的等待消息
如果用户确认他们想要更新 SKIP_WAITING 消息,则旧的激活的服务工作者定义会收到。
这是我的日志的摘录,可以证明这一点。
- 来自应用程序/客户端的日志条目以“应用程序”为前缀,后跟应用程序版本。
- 来自 Service Worker 的日志条目以“Service Worker”为前缀,后跟每个 Service Worker 实例唯一的 DOB 日期戳。
01 [Application 0.0.1.2019.11.05-48] Checking for updates...
02 [Service Worker 2019-11-05 @ 15:23:14] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
03 [Service Worker 2019-11-05 @ 15:23:14] Yay! Workbox 5.0.0-rc.0 is loaded ????
04 [Service Worker 2019-11-05 @ 15:23:14] Lifecycle event: [install]
05 [Application 0.0.1.2019.11.05-48] Service Worker lifecycle event: 06 [externalinstalled]
07 [Application 0.0.1.2019.11.05-48] Service Worker lifecycle event: [externalwaiting]
08 [Application 0.0.1.2019.11.05-48] handle waiting...
09 [Service Worker 2019-11-05 @ 15:20:03] Message event: [SKIP_WAITING]
在线
- 用户刚刚按下了“检查更新”按钮。
- 在
2019-11-05 @ 15:23:14上找到了一个新的 Service Worker 版本,正在对其进行解析。我们称之为 SWv2。 - 工作箱由 SWv2 加载。
- SWv2
install事件处理程序已执行。 - Workbox 窗口
externalinstalled事件处理程序被执行。 - Workbox 窗口
externalwaiting事件处理程序被执行。 - 工作框窗口
externalwaiting事件处理程序使用workboxWindow.messageSW()发送SKIP_WAITING消息 - Service Worker v1(在
2019-11-05 @ 15:20:03上加载)收到跳过等待消息。什么都没发生。 SWv2 仍处于等待状态。
与普通等待事件对比
在以下日志中,您可以看到等待的 Service Worker 收到了 SKIP_WAITING 消息:v 2019-11-05 @ 16:07:32。因此更新过程成功完成。
[Application 0.0.1.2019.11.05-52] Checking for updates...
[Service Worker 2019-11-05 @ 16:07:32] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
[Service Worker 2019-11-05 @ 16:07:32] Yay! Workbox 5.0.0-rc.0 is loaded ????
[Service Worker 2019-11-05 @ 16:07:32] Lifecycle event: [install]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [installed]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [waiting]
[Application 0.0.1.2019.11.05-52] handle waiting...
[Service Worker 2019-11-05 @ 16:07:32] Message event: [SKIP_WAITING]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [redundant]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [activating]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [controlling]
[Service Worker 2019-11-05 @ 16:07:32] Lifecycle event: [activate]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [activated]
[Application 0.0.1.2019.11.05-52] Reloading this window...
[Application 0.0.1.2019.11.05-53] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
[Application 0.0.1.2019.11.05-53] Preloading 125 images...
[Application 0.0.1.2019.11.05-53] ServiceWorker registered!
有时它只是挂起......
有时,当有新的 Service Worker 版本可用时,事情就会卡住。永远不会触发 waiting 或 externalwaiting 事件处理程序。
当这种情况发生时,控制台中没有错误,并且新版本的 Service Worker 也没有任何问题。
解除绑定的唯一方法是停止活动的 Service Worker,取消注册并重新加载。
为什么这很重要?
在我敢发布这个应用程序之前,我需要确保更新过程在所有平台上都能完美运行...
如果用户在我发布更新时遇到这些问题中的任何一个,他们将很难获得更新,而我对此无能为力。乘以安装数量 == 非常头疼。
这一切都归结为三个问题: 按重要性排序:
- 如何处理
externalwaiting,以便加载并激活新版本的Service Worker?如何确保等待的 Service Worker 收到SKIP_WAITING消息? - 为什么生命周期事件在普通品种和外部品种之间会有所不同?
- 出于测试目的,我每次都对 Service Worker 进行相同的更新(预缓存文件的新版本)。
- 我只在一个选项卡中加载了应用程序。
- 从普通事件到外部事件的转换似乎是随机的。
- 为什么进程有时会在生命周期的等待阶段之前卡住,我该怎么办?
【问题讨论】:
-
嘿,过了这么久,我发现了同样的问题。你解决了吗?
-
是的。但不适用于工作箱窗口。不得不使用香草服务工作者 API。我会尽量找时间发表这篇文章。这很复杂。但底线是我不得不放弃工作箱窗口,尽管仍然使用工作箱作为服务工作者,这很好。
-
我们可以聊聊什么吗?我正在为此努力,如果我不必花费大量时间来修复它,我将不胜感激。你可以快速帮助我,我会提出正确的问题。让我知道如何联系您。谢谢你的回答!!!
-
我会尽量抽出时间将我的代码提取到一个可公开访问的示例中并在此处发布链接。您需要解决方案的紧迫程度如何? (我的发送在 Apple 和其他平台/浏览器中运行良好。很遗憾,工作箱团队中没有人对此做出回应......)
-
完全同意。这是一个耻辱。我也做了这个工作。没那么难。
标签: google-chrome-devtools progressive-web-apps workbox workbox-window