全站静态资源缓存需精准识别URL特征、install阶段预载带版本号资源、fetch中仅读缓存不回退网络、activate时清理旧缓存。

用 fetch 事件实现全站静态资源缓存,核心不是“全量缓存”,而是精准识别 + 稳定写入 + 可控响应。重点在于区分哪些该缓,怎么缓得干净,以及如何避免版本混乱。
只对明确静态资源启用缓存逻辑
别用 request.destination === 'script' 这类判断——它在 preload、CORS 请求或某些 CDN 场景下会失效。更可靠的方式是结合 URL 特征匹配:
- 检查路径是否以
/static/、/dist/、/assets/开头 - 用正则匹配后缀:
/\.(js|css|png|jpg|gif|svg|woff2?|ttf|eot|ico|webp)$/i - 排除带敏感参数的请求,比如包含
auth=、session=的 URL - 跳过非 GET 请求(如 POST、PUT),避免误存用户数据或表单响应
install 阶段预载关键资源,确保首次离线可用
光靠 fetch 拦截无法解决“第一次访问就离线”的问题。必须在 install 阶段把确定不变的资源提前写进缓存:
- 使用
caches.open('static-v2.3.1')打开带版本号的新缓存(不要用static这种裸名) - 调用
cache.addAll([ '/dist/app.js', '/dist/main.css', '/assets/logo.svg' ]),路径必须与页面实际请求的 URL 完全一致(含查询参数、大小写、尾部斜杠) - 配合构建工具生成 manifest.json,自动注入真实资源列表,避免手动维护出错
fetch 事件中只读缓存,不 fallback 网络
对已预载的静态资源,要真正实现“离线即用”,fetch 里就不能再发网络请求:
- 命中缓存直接返回:
caches.match(request) - 未命中不调
fetch(request),而是返回new Response('', { status: 404 })或自定义离线提示页 - 不写
event.respondWith(fetch(request))分支——那是缓存优先策略,不是“全站静态缓存” - HTML 页面单独处理,不纳入此逻辑(它需要动态更新,应走缓存+网络并行)
激活时清理旧缓存,防止多版本混用
每次发布新版本,旧缓存若不清理,会导致页面加载错乱资源(例如 v2 的 JS 加载 v1 的 CSS):
- 在 activate 事件中调用
self.clients.claim(),让新 SW 立即接管所有打开页面 - 遍历
caches.keys(),删除所有不含当前版本标识(如v2.3.1)的缓存名 - 确保
skipWaiting()在 install 结束前调用,缩短新旧 SW 共存窗口期

















