service worker预缓存必须在install事件中用event.waituntil()包裹caches.open()和cache.addall()显式写入,任一资源失败即安装中断;需校验路径、避免动态url、清理旧缓存,并理解其离线优先契约本质。

Service Worker 的预缓存(precache)不是“注册了就能用”,它必须在 install 事件中通过 caches.open() 和 cache.addAll() 显式写入,且任一资源加载失败都会导致整个安装失败——这是最常被忽略的硬性约束。
为什么 cache.addAll() 容易让 SW 安装失败
cache.addAll() 是原子操作:只要列表里有一个 URL 返回 404、500 或跨域被拒(比如没配 CORS),Promise 就会 reject,install 事件中断,SW 停留在 waiting 状态,不会激活,也不会拦截后续请求。
- 检查所有
urlsToCache路径是否真实可访问(尤其注意根路径'/'对应的是index.html,不是目录列表) - 避免缓存带时间戳或哈希参数的资源(如
/app.js?v=123),这些 URL 每次构建都变,但 SW 脚本没更新,就会 404 - 静态资源(CSS/JS/图片)建议走构建工具生成固定路径,或用
workbox-precache自动注入清单,别手写死列表
self.addEventListener('install', ...) 里必须用 event.waitUntil()
不包 event.waitUntil(),浏览器会认为 install 立即完成,然后马上执行 activate,此时缓存还没写完,caches.open() 可能还在 pending,cache.addAll() 实际没生效。
- 正确写法必须是
event.waitUntil(caches.open(...).then(cache => cache.addAll(...))) - 如果想分批缓存(比如先核心 HTML/CSS,再补图片),不能直接链多个
addAll(),得用cache.addAll()+cache.put()组合,否则仍受原子性限制 - 开发时可在 Chrome 的 Application → Service Workers 面板勾选 “Update on reload”,强制每次刷新重装 SW,方便验证 install 流程
缓存名(CACHE_NAME)改了,旧缓存不会自动删
只改 CACHE_NAME 并重新注册 SW,新版本会安装并激活,但旧缓存仍躺在 caches.keys() 里,占空间、可能干扰调试。必须显式在 activate 事件里清理。
- 激活阶段要加
caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)))) - 注意:
activate事件只有在没有页面控制权时才立即触发;如果旧 SW 正在运行,新 SW 会卡在waiting,直到所有页面关闭或调用skipWaiting() - 调试时可手动在 Application → Cache Storage 里删掉旧缓存名,比等自动清理更直接
预缓存的本质是「离线优先」的契约:你声明哪些资源必须存在,浏览器就按这个契约校验。路径错一个、权限少一个、时机早一秒,它就不履约——这不是 bug,是设计使然。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











