浏览器工程

Service Worker 更新:别让新旧协议版本同时控制实时任务

设计 install、waiting、skipWaiting 与 clients.claim 流程,避免传输中刷新被新资源接管,并用版本协商和延迟激活保护长任务。

这类问题看似集中在一个 API 或参数上,真正决定可用性的却是状态归属、资源上限和失败后的恢复方式。 强制 skipWaiting 能快速发布,却可能让当前页面继续运行旧 JavaScript、后续请求进入新 Service Worker。若两版缓存、API 或消息协议不兼容,一次普通刷新就会把任务切成两半。

浏览器能力由版本、权限、页面可见性和设备策略共同决定。实现需要能力探测与可解释降级,不能把某一台开发机上的 API 存在当成产品契约。

先把实现决策说清楚

实现之前先列出不可违反的不变量,再为性能与体验留出调节参数。参数可以灰度,身份、权限和终态规则不能在运行时随意漂移。

  • 构建版本写入页面与 worker,激活前查询是否存在传输或共享中的活跃任务。
  • 默认让新 worker waiting,并提供可理解的“任务结束后更新”与手工立即更新。
  • 缓存使用版本化名称,activate 只删除已无客户端使用的旧版本。

Service Worker 更新是运行中版本迁移,不是简单替换文件。让激活时机服从活跃任务,并把协议兼容写进发布测试。

最容易漏掉的失败路径

失败路径需要与成功路径共享同一套状态模型。只弹一个错误提示却不释放资源、不传播终态,下一次恢复就会继承脏状态。

  • 自动 claim 所有客户端,旧页面发出的消息被新 worker 按新 schema 解析失败。
  • 更新提示无限重复,因为页面没有在 reload 后确认已运行目标版本。
  • 离线时删除旧缓存后新资源下载失败,应用壳和进行中任务同时不可用。

上线前怎样验证

测试不能以“最后成功了”结束。还要测量经历了多少次副作用、等待多久、是否泄露内容,以及失败后再次执行能否从干净基线开始。

  1. 在文件传输 1%、50% 与校验期发布新 worker,验证任务策略一致。
  2. 让多个标签分别运行两版,逐个关闭并确认旧缓存只在最后客户端离开后删除。
  3. 更新下载中断网再恢复,确认仍可启动旧壳且不会进入半更新状态。

当实现能够安全降级、重复执行不产生额外副作用、故障指标早于投诉出现时,这项能力才算具备长期维护价值。

把方法变成一次真实连接

打开 uCopy,让两台设备在浏览器里安全连接并开始传输。

开始免费使用