Service Worker 生命周期与缓存:练习答案
install/activate/fetch
导航回退应把 respondWith 限定为 request.mode === 'navigate',并在网络异常时执行 caches.match('/offline.html'):
js
self.addEventListener('fetch', event => {
if (event.request.mode !== 'navigate') return;
event.respondWith(
fetch(event.request).catch(() => caches.match('/offline.html'))
);
});预缓存失败必须让 waitUntil 的 Promise 拒绝。若只记录错误,worker 可能激活,却缺少它假定存在的 shell;后续 caches.match 得到 undefined,错误会延迟到用户请求时才暴露。
Cache-first、network-first 与 stale
/api/profile 需要保存 fetchedAt(可放 IndexedDB 或把时间写入响应元数据)。命中后先判断 Date.now() - fetchedAt <= 300000;新鲜则返回,过期则 network-first,网络失败才返回旧资料,并在页面标注“离线数据”。只用 cache-first 无法表达五分钟新鲜度,也无法区分权限过期。
更新、清理与回滚
v3 预缓存失败时,旧 worker 仍是 active,旧 cache 没有在 install 阶段被删除,所以页面刷新仍能工作。修正资源后浏览器重新安装 v3,activate 才删除旧前缀。skipWaiting() 会跳过等待阶段,可能令旧 HTML 立即收到新资源;除非资源协议兼容并且用户已确认,否则保留 waiting 可避免半更新。