告别缓存冲突与离线白屏:Service Worker 五大缓存策略实战指南
作为前端开发者,你一定遇到过这些抓狂瞬间:明明连着 WiFi,页面却死活不更新最新数据;用户一断网,App 直接白屏报错;或者刚发了新版,用户反馈“我看到的还是上周的页面”。
这些看似玄学的 Bug,90% 都源于同一个问题:缓存策略和实际业务需求不匹配。今天提米哥抛开晦涩的底层原理,用大白话带你彻底搞懂 Cache Storage API 以及五种核心缓存策略。不堆砌概念,只讲怎么选、怎么配,帮你一次搞定离线体验与加载速度的平衡。
Cache Storage 到底是个什么仓库?
简单来说,Cache Storage API 不是用来存账号密码或简单配置的(那是 localStorage 的活儿)。它相当于给网站配了一个“HTTP 响应专属仓库”。
你存进去的不是纯文本,而是完整的“网络请求+返回内容”(包括 HTML、JS 包、CSS 样式、图片甚至 API 接口返回的数据)。用户每次打开网页,浏览器都可以先问这个仓库:“用户要的货,你这里有吗?”有就直接秒出,没有再去网上进货。
新手避坑的三个关键细节:
– 只支持 GET 请求:填表提交、支付接口等 POST 请求不能存这里,得靠 IndexedDB 配合后台同步。
– 全异步操作:所有读写动作都是非阻塞的。写代码时一定要记得加 await,否则极易出现静默失败,控制台还不报错。
– 建议分仓管理:生产环境强烈建议按类型建多个仓库(例如 app-shell 放框架代码,api-data 放接口数据,media 放图片)。这样版本更新时,可以精准清空某个仓库,不影响其他模块。
五大核心策略:到底该选哪个?
缓存设计只问自己一个问题:“先读本地旧货,还是先读网络新货?” 下面五种策略覆盖了几乎所有业务场景:
- 策略一:缓存优先(Cache First)
- 运行逻辑:先查本地仓库,找到了直接给用户看,不走网络;找不到再去网上拉并入库。
- 适用场景:几乎不变动的静态资源。特别是带哈希值/版本号的 JS、CSS、字体、用户上传的图片。因为文件名变了就是新版本,本地没的会自动去下,本地有的直接秒加载。
-
致命风险:千万别用在文件名固定的资源上(比如
/main.css)。否则仓库一旦存下旧版,用户永远刷不到新版。 -
策略二:网络优先(Network First)
- 运行逻辑:先去网上拉最新内容,拉成功就展示并更新仓库;如果用户断网,就退回仓库拿上次存的旧版。
- 适用场景:强时效性内容(新闻流、商品库存、个人账户信息)。保证在线用户永远看到最新数据。
-
优化技巧:网速慢时会严重拖慢体验。最佳实践是加个“超时熔断”:如果网络超过 3~5 秒没返回,直接显示仓库里的旧数据先稳住用户,同时后台默默下载新版,下次访问就是新的。
-
策略三:先旧后更(Stale-While-Revalidate)
- 运行逻辑:不管网络状态,优先从仓库拿旧数据秒开页面给用户看。同时后台默默发起网络请求,拉取新数据并静默替换旧缓存。
- 适用场景:对绝对实时要求不高,但极度追求流畅感的内容(博客目录、个人设置页、帮助文档、非核心配置)。
-
定位:这是大多数“中间地带”内容的最佳默认策略。它完美卡在“性能”和“新鲜度”中间,用户无感刷新,后台持续保鲜。
-
策略四:仅走网络(Network Only)
- 运行逻辑:完全绕过仓库,每次强制走网络。
-
适用场景:带副作用、绝对不能缓存的请求(表单 POST、支付网关、登录验证、埋点上报)。这些操作一旦缓存会导致数据错乱或重复提交。非 GET 请求默认就是这种处理方式。
-
策略五:仅读缓存(Cache Only)
- 运行逻辑:只看仓库里存的,绝不去网上拉。
- 适用场景:提前打包好、必须离线的“应急兜底页”(比如“网络连接中断”的插画提示页),或强制离线演示环境。
- 使用警告:慎用!如果刚好没预缓存这个文件,页面会直接返回空白。只有 100% 确认文件已在仓库里时才用。
实战怎么组合出拳?
真实项目从来不是“一刀切”,而是按 URL 规则路由匹配。一个成熟的新闻/电商类应用通常是这样搭配的:
– 核心框架与静态资源:用 缓存优先,确保首屏加载飞快。
– 首页列表与推荐流:用 网络优先+超时机制,在线保新鲜,弱网保可用。
– 用户偏好与历史记录:用 先旧后更,兼顾打开速度与数据同步。
– 提交订单/点赞接口:用 仅走网络,保障交易安全与数据准确。
– 离线占位页:用 仅读缓存,断网时提供友好的降级提示。
仓库容量会爆吗?
浏览器对每个站点能存多少数据有严格配额(跟设备剩余磁盘空间挂钩)。空间快满时,系统会自动按“最近最少使用”原则清理旧缓存。如果你希望核心缓存永久驻留,可以调用 navigator.storage.persist() 申请持久化存储(具体看浏览器策略,可能触发用户授权提示)。
把对的工具放在对的场景里,你的 Web 应用就能在“秒开速度”与“数据鲜活”之间找到最优解。别再让错误的缓存逻辑拖垮产品体验了。
