stale-while-revalidate是一种缓存策略:请求一来立即返回缓存响应(无论是否过期),同时后台静默发起fetch更新缓存;它不是network-first,也不是过期后才拉新,核心是“即时响应+异步刷新”。

stale-while-revalidate 是什么,不是什么
它不是“先等网络再给缓存”,也不是“缓存过期后才去拉新”。stale-while-revalidate 的本质是:请求一来,立刻返回缓存响应(哪怕已过期),同时在后台静默发起 fetch(),拿到新响应后更新缓存——用户无感,后续访问自动生效。
常见错误现象包括:页面加载明显变慢(误当成 network-first)、内容长期不更新(没触发后台 fetch)、或控制台报 TypeError: Failed to execute 'clone' on 'Response': Response body is already used(没用 response.clone() 分发)。
fetch 事件里怎么写一个可靠的 stale-while-revalidate 处理
关键不在“有没有”,而在“顺序对不对”和“流用没用完”。必须在 event.respondWith() 中第一时间返回缓存,再启动后台更新。
- 用
request.destination === 'document'或new URL(event.request.url).pathname === '/'精准识别首页导航请求 - 调用
caches.match(event.request)获取缓存响应;若存在,立即return response - 无论是否命中缓存,都应执行
const fetchPromise = fetch(event.request) - 新响应到达后,必须先
const cloned = response.clone(),一份传给浏览器(仅限未命中的 fallback 场景),一份写入缓存:cache.put(event.request, cloned) - 不要在
fetchPromise.then()里直接return response给respondWith(),那会阻塞首屏
为什么不能只靠 install 阶段预缓存
预缓存(install 阶段的 cache.addAll())解决的是“第一次有东西可拿”,但 HTML 这类资源通常带构建哈希或服务端渲染,版本一变,旧缓存就失效。纯预缓存无法应对动态更新。
容易踩的坑:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 把未哈希的
/index.html写进urlsToCache→ 每次部署后用户仍看到旧首页 - 在
install中缓存 API 接口(如/api/user)→ 缓存空响应或 401,且无法自动刷新 - 没配
activate清理逻辑 → 多个版本缓存共存,占用存储,甚至导致caches.open()失败
正确做法:静态资源(CSS/JS/图片)走预缓存 + CacheFirst;HTML 和关键 API 走运行时 stale-while-revalidate。
导航预加载(navigation preload)怎么配合它
冷启动 Service Worker 时,fetch 事件可能延迟 100–300ms 触发,这期间用户看到白屏或加载 spinner。导航预加载就是为填这个空档。
实操要点:
- 注册时必须调用
registration.navigationPreload.enable(),否则event.preloadResponse始终为undefined - 在
fetch事件开头优先检查if (event.preloadResponse),有则直接return event.preloadResponse - 它和
stale-while-revalidate是并行关系,不是替代关系:预加载响应可当作“临时缓存”用一次,之后仍要走完整缓存+后台更新流程 - iOS Safari 自 11.3 起支持,但需注意:若服务器未返回
Content-Length或响应过大,预加载可能被浏览器中止
最易被忽略的一点:stale-while-revalidate 的“新鲜度”完全依赖后台 fetch 是否成功。如果网络彻底断开、或接口返回 5xx,缓存就不会更新——你得靠 catch 块兜底记录错误,而不是假设它总能刷新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










