cache-first适合静态资源与离线优先场景,先查缓存、命中即返、未命中再网络请求并缓存;network-first适合动态内容,优先网络确保新鲜度,失败才回退缓存。

选 Cache-First 还是 Network-First,关键看资源是否需要“即时性”和“一致性”。静态资源优先保速度,动态内容优先保新鲜度。
Cache-First:适合不变或低频更新的资源
这类策略先查缓存,命中就直接返回,不发网络请求;未命中才走网络,并把响应存入缓存。它让二次访问极快,且天然支持离线使用。
-
CSS、JS、字体、Logo、图标:构建时已哈希命名(如
main.a1b2c3.js),内容变更即路径变化,缓存可长期有效 - 离线优先场景:比如内部管理后台、文档查看器、PWA 类应用首页,用户打开即用,不依赖实时联网
-
注意点:必须配合版本化缓存名(如
static-v2)和 activate 阶段清理旧缓存,否则更新不生效
Network-First:适合需强一致性的动态内容
先发起网络请求,成功则返回并缓存;失败(超时、断网、5xx)时才回退到缓存。它兼顾新鲜与兜底,但首次加载无法跳过网络延迟。
- 用户数据类接口:如消息列表、订单状态、个人资料——用户期望看到最新结果,但也不能因网络抖动白屏
- 新闻/公告类页面:内容每日更新,但离线时仍应展示昨日版本,比空白页更友好
- 注意点:需设置合理的 fetch 超时(Service Worker 中无原生 timeout,可用 Promise.race 模拟),避免卡死等待
别只盯策略,还要配好生命周期
策略再合适,若 SW 生命周期没理清,更新就会失效。常见问题多出在 install/activate 阶段:
-
install 阶段:用
event.waitUntil()开缓存、预存资源;加self.skipWaiting()让新版 SW 不等旧标签页关闭就准备激活 -
activate 阶段:用
self.clients.claim()立即接管当前页面;遍历caches.keys()删除旧缓存,防止脏数据堆积 -
fetch 阶段:按 URL 规则分流——比如以
/api/开头走 Network-First,.css或.png后缀走 Cache-First
进阶建议:混合使用更真实
实际项目很少全站统一一种策略。更合理的是按资源类型分层处理:
- HTML 页面:Cache-First + navigationPreload(启用导航预加载,提升首屏速度)
- 静态资源(JS/CSS/图片):Cache-First,配合内容哈希与版本缓存名
- API 接口:Network-First,失败时 fallback 到缓存,并添加时间戳判断是否过期(如缓存超过 5 分钟则不复用)
- 关键兜底页(如 /offline):单独预缓存,确保 Network-First 失败后有体面降级











