Service Worker 生命周期失败需要恢复计划,而不仅仅是安装代码
你的 Service Worker 可能会在用户毫无察觉的情况下安装失败。这里是如何检测、恢复并保持用户参与度的方法。
为什么这很重要
如果 Service Worker 的安装或激活失败,你的 PWA 就会处于损坏状态。浏览器会继续提供旧版本的内容,而用户可能不会意识到出了问题。静默失败是最糟糕的一种——它在没有任何机会修复的情况下就侵蚀了信任。
生命周期陷阱
Service Worker 不会自动接管控制权。新的 Worker 会经历三个状态:安装中(installing)、等待中(waiting)、激活中(activating)。等待与激活之间的转换只会在以下情况发生:
- 没有任何标签页或窗口被旧 Worker 控制,或
- 你在安装处理程序中显式调用
self.skipWaiting()
如果安装失败——网络错误、manifest 格式错误或运行时异常——旧的 Worker 会继续提供内容。你的更新实际上被阻断了。
恢复检查清单
检测失败的安装:
// 在你的安装处理程序中
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v2').then((cache) => {
return cache.addAll([
'/',
'/offline.html'
]);
}).catch((error) => {
// 记录这个错误
console.error('Service worker install failed:', error);
throw error; // 让安装显式失败
})
);
});处理更新冲突:
// 追踪新 Worker 是否在等待
const isUpdateAvailable = () => {
return navigator.serviceWorker.getRegistration().then((registration) => {
return registration && registration.waiting;
});
};
// 当更新可用时提示用户
if (isUpdateAvailable()) {
showUpdatePrompt();
}没有 Worker 时的优雅降级:
当 Service Worker 损坏时,你的 PWA 仍应能使用。提供缓存的 shell 或回退到网络。不要因为 Worker 失败就阻止所有用户操作。
何时使用 skipWaiting()
在安装处理程序中调用 self.skipWaiting():
✅ 适用于:
- 需要立即部署的关键安全补丁
- 阻止用户完成核心任务的 Bug 修复
- 不会中断进行中操作的更新
❌ 不适用于:
- 可能在会话过程中让用户困惑的重大 UI 改造
- 可能破坏进行中事务的数据迁移
- 改变客户端页面所依赖的 API 契约的更新
监控与告警
在生产环境中追踪 Service Worker 的健康状态:
- 将安装失败记录到你的错误追踪系统
- 测量新版本推出与用户采用它们之间的时间
- 如果等待的 Worker 等待时间过长(表示卡住的安装),则发出告警
对开发者的建议
Service Worker 生命周期是一个延迟更新系统。充分利用它。设计更新时,让它们至少在一个发布周期内与前一版本兼容。这为你提供了一个自动回滚的安全网,以防出现故障。
下一步
- 在你的 Service Worker 安装处理程序中添加错误追踪
- 为等待中的 Worker 实现用户可见的更新提示
- 测试失败场景:安装中途网络断开、格式错误的缓存条目、运行时异常
- 为生产环境 PWA 构建"Service Worker 健康"仪表板
你的 PWA 的可靠性取决于它如何处理意外情况,而不仅仅是一切正常时的表现。