Cache API 与 IndexedDB 各司其职:前者缓存 HTTP 请求/响应(如静态资源、API 原始响应),后者存储可查询的结构化业务数据(如待办、草稿);二者协作覆盖完整离线场景。

IndexedDB 和 Cache API 各有定位,不互为替代,但在离线场景中能形成高效协作:Cache API 负责缓存网络请求(特别是静态资源和 API 响应),IndexedDB 则存储结构化、需查询或持久化的业务数据。二者配合使用,才能覆盖完整的离线需求。
明确分工:什么该进 Cache,什么该进 IndexedDB
Cache API 适合存储 HTTP 请求/响应对,例如 HTML、CSS、JS、图片、JSON 接口返回的原始响应体。它天然支持 Service Worker 拦截与匹配,且读写基于 URL 键,无需手动序列化。
IndexedDB 适合存储 结构化、可索引、需增删改查的数据,比如用户表单草稿、离线消息队列、带时间戳的同步状态、本地生成的富文本内容等。它支持事务、游标遍历、多索引查询,但需要手动解析响应体(如 response.json())后再存入。
- 静态资源(logo.png、main.css)→ Cache API
- 首页 HTML(通过 fetch 获取)→ Cache API(可配合 navigation preload)
- 用户提交但未同步的订单 → IndexedDB(含 status、createdAt、items 等字段)
- 分页列表接口返回的 JSON 数据 → 可先存 Cache(供快速复用),再解析后按需存 IndexedDB(供离线筛选或关联查询)
典型协作流程:一次离线加载与后续同步
以一个待办应用为例:
立即学习“前端免费学习笔记(深入)”;
- 安装阶段:Service Worker 预缓存核心静态资源(via Cache API)
- 首次联网运行:fetch 主页数据(如
/api/todos),将响应克隆一份存入 Cache(URL 为键),同时解析 JSON 后批量写入 IndexedDB - 离线访问时:
– 页面资源直接从 Cache API 读取(Service Worker 响应)
– 待办列表从 IndexedDB 查询并渲染(不依赖网络) - 用户新增待办:先写入 IndexedDB(标记
syncStatus: 'pending'),界面立即更新;网络恢复后,由后台同步逻辑读取 pending 记录,调用 API 提交,并成功后更新 IndexedDB 中的状态
避免常见协作陷阱
Cache API 的响应体是只读流,不能重复读取。若既要缓存响应,又要解析数据存 IndexedDB,必须显式 clone():
const response = await fetch('/api/data');
const cachedResponse = response.clone(); // 用于 cache.put()
const data = await response.json(); // 用于 indexedDB.put()
await caches.open('api-cache').put('/api/data', cachedResponse);
// …再把 data 存入 IndexedDB
另外,不要用 Cache API 存储大量非响应类数据(如用户输入片段),它没有查询能力;也不要用 IndexedDB 替代 Cache 来缓存资源,会失去 HTTP 语义(如 ETag、Vary 处理)和 SW 的自动匹配优势。
清理与版本管理需协同
应用升级时,常需清旧缓存 + 迁移数据库。建议在 Service Worker activate 事件中统一处理:
- 调用
caches.delete('old-cache-name')清理过期 Cache - 打开 IndexedDB 时指定新版 version,监听
onupgradeneeded进行 schema 迁移(如新增索引、重命名对象仓库) - 迁移完成后,再触发一次全量数据预填充(如重新 fetch 并存入新 Cache 和 IndexedDB),确保离线体验一致
不复杂但容易忽略。











