实现秒开离线缓存的关键是立即调用event.respondWith()、精准匹配URL(注意查询参数)、Response流必须clone后双用、activate阶段彻底清理旧缓存。

别用 manifest,它在 Chrome 95+、Firefox 85+、Safari 16.4+ 已彻底移除,加了也完全不生效。当前唯一可行的断网离线缓存方案是 Service Worker,且必须走 HTTPS(localhost 除外)。
Service Worker 注册失败的典型表现和自查点
页面刷新后 DevTools → Application → Service Workers 面板为空,或显示 “No service worker registered” —— 这不是代码没写,而是注册根本没触发。
-
navigator.serviceWorker是undefined:说明当前上下文不安全,检查是否用了 HTTP(非localhost) - 注册脚本执行了但没反应:打开 Network 面板,看
sw.js是否返回 404、302 或响应头含Cache-Control: no-cache/must-revalidate(Nginx/Apache 常误配) - 有旧 SW 卡在
waiting状态:新版本不会自动激活,需手动调用self.skipWaiting()或在 DevTools 中点击 “Skip Waiting” - 注册路径错误:
navigator.serviceWorker.register('/js/sw.js')要求该路径真实可访问,且返回 MIME 类型为text/javascript
install 阶段缓存失败的常见原因
cache.addAll() 是原子操作,列表中任一资源 fetch 失败(404、跨域、MIME 不匹配、no-store 响应头),整个缓存就中断,SW 永远卡在 installing 状态。
- 写了
['/index.html'],但服务器返回的是动态 HTML 且带Cache-Control: no-store→ 缓存直接拒绝 - 路径用相对写法,比如
sw.js在/js/sw.js下注册,却写./style.css→ 解析成/js/./style.css,404 - 清单里写
/images/logo.png,实际文件是/images/Logo.PNG(Linux 服务器区分大小写) - HTML 文件本身依赖 JS/CSS,但只缓存了 HTML,没缓存
/app.js或/main.css→ 断网时 HTML 加载成功,但内嵌脚本 404,功能全挂
fetch 事件里如何正确 fallback 到缓存
只写 caches.match(event.request).then(r => r || fetch(event.request)) 是危险的:它会把 POST 请求、带 credentials 的请求也去缓存里查,导致登录态丢失或表单静默失败。
立即学习“前端免费学习笔记(深入)”;
- 优先识别 HTML 页面请求:
event.request.destination === 'document',这类才做“缓存优先 + 网络兜底” - 对
'script'、'style'、'image'等静态资源,可直接caches.match()返回,无需再 fetch - 对
'json'或'document'以外的 API 请求(如/api/user),建议明确放行到网络,避免返回过期数据 - 不要缓存带查询参数的 URL(如
/data.json?v=1.2),不同参数会被当不同键,快速撑爆 CacheStorage 限额
最易被忽略的一点:即使 install 成功、activate 完成,首次访问页面时仍走网络;只有**第二次及以后的访问**,才能真正离线加载。这不是 bug,是 Service Worker 的设计机制——缓存只对后续导航生效。



















