Service Worker 在低配 Android 设备上易被系统强制终止,导致离线失效;需通过 ping 探测、controller 监听与状态轮询识别失活,采用渐进式注册、skipWaiting、精简缓存及页面生命周期唤醒实现轻量自愈,并辅以降级提示与 localStorage 回退。
service worker 在低配置 android 设备上被系统强制终止(如进入休眠、内存回收或电池优化触发的进程清理),是 pwa 离线能力失效的常见根源。它并非代码报错,而是运行环境被系统静默干预——此时 sw 不再响应 fetch、activate 或 message 事件,用户刷新页面即退化为纯在线模式。解决关键不在于“阻止杀死”,而在于构建可检测、可恢复、低开销的自愈机制。
识别 SW 是否已失效
不能依赖 navigator.serviceWorker.ready,它只反映注册状态,不保证活跃性。需主动探测:
- 在页面加载时,向 SW 发送轻量 ping 消息(
postMessage({type: 'ping'})),并设置 1.5 秒超时;无响应即判定为失活 - 监听
navigator.serviceWorker.controller变为null的时机(例如用户长时间切后台后返回) - 定期轮询(如每 30 秒)检查
self.registration.active和waiting状态,二者同时为null即代表当前无有效控制 SW
轻量级自愈注册策略
避免全量重注册引发资源争抢。采用渐进式恢复:
- 失活确认后,立即调用
navigator.serviceWorker.register('/sw.js', { updateViaCache: 'none' }),强制绕过浏览器缓存获取最新脚本 - 注册成功后,不等待 activate 完成,先用
skipWaiting()让新 SW 尽快接管,减少空白期 - 对低配设备(可通过
navigator.deviceMemory < 2或 UA 特征粗筛),禁用非核心缓存逻辑(如图片/字体预缓存),仅保留 HTML、JS、CSS 三级核心资源缓存,降低 SW 内存占用
利用页面生命周期维持 SW 存活
借助 Page Visibility API 和 Focus 事件延长 SW 生命周期:
- 页面获得焦点时,主动触发一次空
fetch请求(如fetch('/__noop', {cache: 'no-store'})),唤醒 SW 线程 - 监听
visibilitychange,当页面从 hidden 切回 visible,立即发送消息同步关键状态(如购物车变更、未提交表单) - 避免在 SW 中执行长耗时操作(如遍历大 CacheStorage、解析大 JSON),改用 indexedDB 分片处理 + requestIdleCallback 调度
降级兜底与用户提示
自愈失败时,提供明确反馈而非静默降级:
- 检测到连续 2 次 ping 失败,显示底部横幅:“离线功能暂时不可用,正在尝试恢复…” 并提供手动刷新按钮
- 若设备明确处于省电模式(通过
navigator.getBattery()判断 battery.level < 0.15 且 charging === false),提示用户“为保障离线体验,建议关闭省电模式” - 所有 fetch 请求增加 fallback 逻辑:SW 失效时自动回退至网络请求,并缓存响应结果到 localStorage(限小文本类数据),供下次页面加载时读取

















