indexeddb加速spa启动的核心是“少等、少算、少传”,通过预加载登录态、路由元信息等结构化数据到本地,配合版本管理、复合索引、分片读取及service worker协同,实现离线优先、快速首屏渲染。

直接用 IndexedDB 加速 SPA 启动,核心不是“存更多”,而是“少等、少算、少传”。关键在于把原本依赖网络请求和前端解析的启动阶段数据,提前固化为可快速读取的本地结构化缓存。
预加载关键启动数据到 IndexedDB
首次访问后,将登录态、用户配置、路由元信息、静态菜单、权限规则等不常变但启动必用的数据,在空闲或后台同步写入 IndexedDB。下次启动时,直接从库中读取,绕过 API 请求和 JSON 解析开销。
- 避免存整个 bundle 或 HTML——IndexedDB 不适合存大块二进制资源,那是 Service Worker 和 Cache API 的职责
- 优先存结构化对象(如
{ userId: 'u123', theme: 'dark', permissions: ['read', 'edit'] }),而非字符串或未解析的 JSON 文本 - 配合版本号管理:每次数据结构变更时升级数据库版本,在
onupgradeneeded中迁移旧数据,防止读取失败
用索引加速启动态查询
启动时往往需要按条件快速捞出某类配置,比如“当前用户可见的导航项”或“默认首页模块”。这时仅靠 getAll() 或遍历会拖慢首屏。
- 为高频筛选字段建复合索引,例如:
objectStore.createIndex('role_status', ['role', 'status'], { unique: false }) - 查询时用
IDBKeyRange.bound精确限定范围,避免游标全扫;对分页类需求(如取前 5 个默认 tab),用cursor.advance(n)跳过无关项 - 低选择性字段(如
status: 'active'/'inactive')单独建索引意义不大,应与高选择性字段组合使用
分片读取 + 异步解耦 UI 渲染
即使数据已本地化,一次性读取几千条记录仍可能造成主线程抖动,影响 TTI(Time to Interactive)。
- 对批量启动数据(如用户最近打开的 100 个页面记录),按需分片读取:先读前 10 条撑起骨架,再用
setTimeout或requestIdleCallback加载剩余部分 - 读取操作必须走事务,并监听
onsuccess或用 Promise 封装,确保不阻塞后续逻辑 - 避免在
onload或mounted钩子中同步等待 IndexedDB 结果;改为“先渲染默认态,再异步替换”
结合 Service Worker 实现离线优先启动
IndexedDB 单独无法解决网络不可用时的启动问题。需与 Service Worker 配合,形成两级缓存策略:
- Service Worker 缓存 HTML、JS、CSS 等静态资源,保证页面能加载
- IndexedDB 存业务数据,让页面加载后能立刻展示有意义的内容(如离线草稿、缓存的商品列表)
- 启动时优先尝试从 IndexedDB 读取最新数据;若失败或为空,再 fallback 到 SW 缓存的兜底数据或骨架屏











