indexeddb 与 service worker 分工协同:前者专注数据存储与查询,后者负责请求调度与同步策略;二者职责不越界、数据流不阻塞、更新不丢漏。

IndexedDB 和 Service Worker 不是简单叠加,而是分工明确、协同工作的组合:前者管“存什么、怎么查”,后者管“什么时候存、什么时候同步、怎么兜底”。真正高性能的离线架构,核心在于两者职责不越界、数据流不阻塞、更新不丢漏。
明确角色边界:谁负责什么
Service Worker 是请求调度中枢,不直接操作业务数据;IndexedDB 是本地数据仓库,不参与网络决策。
- Service Worker 拦截 fetch 请求,判断是走缓存、走网络,还是先读 IndexedDB 再发请求
- 所有增删改查 IndexedDB 的逻辑,统一放在页面主线程(或 Web Worker)中执行,避免在 SW 中做耗时数据库操作
- SW 只在需要时通过 postMessage 向页面发送同步指令(如“网络已恢复,请上传待同步数据”),由页面触发 IndexedDB 写入或上传逻辑
分层缓存策略:静态资源 + 动态数据分离
Cache API 和 IndexedDB 各司其职,不能混用:
- 静态资源(HTML/CSS/JS/图片/字体)用 Cache API 预缓存,版本化管理(如 'v2-app-shell'),确保离线可加载页面骨架
- 动态内容(用户笔记、API 响应体、表单草稿、聊天记录)存 IndexedDB,按业务建 object store,例如:notes、api-cache、sync-queue
- 避免把 JSON 响应体直接塞进 Cache API——它不支持按字段查询,也不支持事务,无法做增量更新或冲突处理
事务与索引:让 IndexedDB 真正快起来
性能瓶颈往往不在容量,而在查询方式。主键索引只够用,高频路径必须补二级索引:
- 待办列表按状态筛选?给 completed 字段建非唯一索引
- 搜索历史按关键词+时间排序?建复合索引 [keyword, timestamp]
- 同步队列需按优先级和时间重试?用 priority 和 nextRetryAt 联合建索引
- 批量写入务必复用同一事务:一次 readwrite 事务内调用多次 store.put(),比开十个事务快数倍
离线写入与同步闭环:本地优先,后台自动
用户操作永远以本地成功为第一反馈,网络同步是后台任务:
- 新增一条记录,先写 IndexedDB,标记 synced: false,立即渲染;不等网络返回
- 监听 navigator.onLine 或利用 Service Worker 的 background sync(若支持),触发同步逻辑
- 同步失败时,保留原始记录,更新 retryCount 和 nextRetryAt(指数退避),下次联网再试
- 服务端返回成功后,再更新本地 synced: true 和 serverId,完成闭环











