
一、什么是 IndexedDB1.1 简介IndexedDB 是浏览器提供的客户端事务型 NoSQL 数据库专为存储大量结构化数据而设计支持异步操作、事务机制和索引查询适用于构建离线优先的 Web 应用如PWA-Progressive Web App渐进式 Web 应用。其核心价值在于突破 localStorage 的容量与性能限制允许直接存储复杂对象、二进制数据Blob并通过索引实现高效查询同时避免阻塞主线程。IndexedDB 是 W3C 推荐的浏览器原生客户端数据库标准作为 WebSQL 被弃用后的主流替代方案。它属于 NoSQL 类型数据库以对象仓库Object Store而非表格形式组织数据数据以键值对形式存储支持 JavaScript 对象、数组、Blob 等复杂类型无需序列化。若需简化开发可使用封装库如Dexie.js、localForage它们提供 Promise API 和自动降级支持大幅降低原生 IndexedDB 的复杂度。实际项目中应优先评估数据规模与查询需求——当数据量 100KB 或需复杂查询时IndexedDB 是比 localStorage 更可靠的选择。与 localStorage/WebSQL 的关键区别对比维度 localStorage / WebSQL IndexedDB容量上限 通常限制为 5MB且同步操作易阻塞 UI 无固定上限一般 ≥250MB可达设备空闲磁盘的 50%~60%数据操作方式 仅支持字符串键值对无索引和事务支持 通过事务机制保证数据一致性并支持多字段索引加速查询同步性 操作是同步的大数据量时会导致界面卡顿 完全异步通过事件或 Promise 执行不阻塞主线程1.2 关键特性1核心能力事务支持操作必须在事务中执行支持 readonly 和 readwrite 模式。事务具备原子性——任一操作失败则整个事务回滚确保数据一致性。索引优化查询可为对象仓库的任意字段创建索引如name、updated_at避免全表扫描。时间范围查询需配合 IDBKeyRange.bound() 使用。二进制数据存储直接存储 Blob/File 对象如图片、视频无需转换为 Base64 字符串适用于离线资源缓存。2限制与约束同源策略数据库仅限创建它的同源页面访问无法跨域读写。版本控制机制数据库通过整数版本号管理结构变更。版本号必须为整数如2.1 会被取整为 2升级时需触发 onupgradeneeded 事件迁移数据。隐身模式行为数据仅驻留在内存中关闭窗口后自动清除且配额通常 ≤120MB常规模式可达数 GB。1.3 核心概念架构1核心组件组件 说明数据库 顶层容器每个数据库有唯一名称和整数版本号。对象仓库 类似 NoSQL 的“集合”存储键值对数据。必须指定主键路径keyPath。索引 基于字段的快速查询通道可设为唯一unique: true或非唯一。事务 操作的原子单元限定作用域如db.transaction([‘users’], ‘readwrite’)。2数据组织逻辑主键设计优先使用业务主键如user_id、message_id作为 keyPath避免依赖自增 IDautoIncrement导致多端同步冲突。分域存储按业务拆分对象仓库如user_settings、chat_messages避免单表膨胀导致锁竞争。1.4 基本操作初始化、增、删、改、查、索引查询// 【初始化】const request indexedDB.open(“MyDB”, 1); // 名称版本号// 首次创建或升级版本时触发request.onupgradeneeded (event) {const db event.target.result;// 创建对象仓库主键为 idconst store db.createObjectStore(“users”, { keyPath: “id” });// 为name字段添加索引store.createIndex(“name”, “name”, { unique: false });};request.onsuccess (event) {const db event.target.result; // 获取数据库实例};// 关键点版本升级逻辑必须在 onupgradeneeded 中完成否则无法修改结构const tx db.transaction(“users”, “readwrite”);const store tx.objectStore(“users”);// 【添加数据 add】const request store.add({ id: 1, name: “Alice”, age: 25 }); // 主键需唯一request.onsuccess () console.log(‘数据添加成功’);request.onerror (event) console.error(‘数据添加失败:’, event.target.errorCode);// 【删除数据 delete】const request store.delete(id);request.onsuccess () console.log(‘数据删除成功’);request.onerror (event) console.error(‘数据删除失败:’, event.target.errorCode);// 【修改】const request store.put({ id: 1, name: “Alice”, age: 26 });request.onsuccess () console.log(‘数据更新成功’);request.onerror (event) console.error(‘数据更新失败:’, event.target.errorCode);// 【简单查询 get】const request store.get(id);request.onsuccess (event) {if (event.target.result) {console.log(‘查询结果:’, event.target.result);} else {console.log(‘未找到 ID 为’, id, ‘的数据’);}};request.onerror (event) console.error(‘数据查询失败’, event.target.errorCode);// 【索引查询】const index store.index(“name”);// 查询所有 name “Alice” 的记录index.getAll(“Alice”).onsuccess (e) console.log(e.target.result);除了 getAll()IndexedDB 的索引对象还提供了其他几种常用的查询方法以应对不同的业务场景方法 说明 返回值index.get(value) 获取匹配该索引值的第一条记录 单个对象或 undefinedindex.getAll(value) 获取匹配该索引值的所有记录 数组 []index.getAllKeys(value) 获取匹配该索引值的所有主键 主键数组 []index.count(value) 统计匹配该索引值的记录数量 数字 Number注意事务上下文在执行 store.get() 或 store.index() 之前请确保当前处于一个有效的 readwrite 或 readonly 事务Transaction中。如果事务已经结束或发生错误调用这些方法会抛出异常。索引必须提前创建store.index(“name”) 中的 “name” 必须在数据库初始化onupgradeneeded时通过 objectStore.createIndex(‘name’, ‘name’, { unique: false }) 创建过否则会报错。分批提交单次事务写入 500~2000 条避免长时间阻塞。主动让出主线程用 queueMicrotask 或 setTimeout 间隔执行批次。1.5 典型应用场景1离线优先应用PWA离线数据持久化用户操作实时存入 IndexedDB网络恢复后同步至服务器。配合 Service Worker缓存静态资源Cache APIIndexedDB 存储动态数据实现完整离线体验。2大数据量客户端缓存结构化数据缓存商品目录、用户历史记录等 100KB 的数据避免频繁请求服务器。性能敏感场景对比测试显示2 万条商品数据约 4.8MB的读写IndexedDB 比 localStorage 快 3.8~6.3 倍索引查询效率提升 ≥16 倍。3二进制资源管理图片/文档本地缓存存储 Blob 数据实现“秒开”体验如文档查看器、图片库。游戏状态保存关卡进度、玩家属性等需结构化存储的场景。1.6 使用注意事项与最佳实践1工程化设计原则按业务域拆分仓库避免将用户配置、日志、临时数据混存于同一对象仓库。索引精简化仅高频查询字段建索引长文本字段如content不适合索引全文检索应交由专用库如FlexSearch。2容量与清理策略主动监控配额通过 navigator.storage.estimate() 检测用量当 usage/quota 0.8 时触发清理。分级清理机制优先删除带 expiresAt 的临时数据如日志再清理旧快照避免误删核心数据。3隐私与安全敏感数据加密IndexedDB 本身 无内置加密存储密码等信息需先通过 Web Crypto API 加密。隐身模式限制数据仅内存驻留关闭窗口即销毁不可依赖其持久化能力。回到顶部二、什么是 Cache storage2.1 简介Cache Storage 是浏览器提供的专用于缓存网络请求/响应对Request/Response的持久化存储机制由开发者通过 JavaScript 显式控制独立于 HTTP 缓存头主要用于实现离线优先的 Web 应用如PWA。其核心价值在于完全自主管理资源缓存策略如离线访问、网络回退而非依赖服务器设置的缓存规则。Cache Storage 将缓存控制权交给开发者使其能精准实现离线场景需求。实际使用时应避免将其视为“自动缓存”工具——所有缓存操作必须显式编码且需严格管理生命周期。对于简单场景可结合 workbox 等库简化策略实现若仅需缓存静态资源优先通过 HTTP 头配置强缓存而非过度依赖 Cache Storage。Cache Storage 是 W3C Service Workers 规范的一部分但 不限于 Service Worker 环境也可在主线程通过 caches 全局对象访问。它专为存储 HTTP 请求-响应对设计直接缓存二进制资源如HTML、CSS、JS、图片而非结构化数据后者应使用 IndexedDB。Cache Storage 与 HTTP 缓存的关键区别对比维度 HTTP 缓存 Cache Storage控制权归属 由服务器通过 Cache-Control / Expires 响应头控制。 完全由开发者通过代码管理忽略 HTTP 缓存头。缓存粒度 基于 URL 和响应头自动生效。 需显式调用 API 添加/匹配资源支持自定义匹配逻辑如忽略查询参数。适用场景 适用于常规页面加载加速。 专为离线场景设计如PWA 的离线资源预加载。2.2 核心特性与限制1关键能力持久化存储缓存数据跨页面刷新和浏览器会话保留除非开发者主动删除。独立于网络请求可通过 caches.match(request) 手动检查缓存无需实际发起网络请求。灵活匹配策略支持自定义匹配逻辑如忽略 URL 查询参数通过 Cache.match(request, options) 的 options 参数控制。2重要限制仅支持 GET 请求Cache.add()/addAll()/put() 无法缓存 POST 等非安全请求。HTTPS 强制要求生产环境中必须通过 HTTPS 服务本地开发可使用 http://localhost否则 API 调用会抛出 SecurityError。存储空间受配额约束浏览器对单域名缓存总量有上限通常为设备空闲磁盘的 50%~60%需通过 navigator.storage.estimate() 监控用量。2.3 核心 API 与工作流程基础操作方法有方法 作用caches.open(cacheName) 打开指定名称的缓存仓库若不存在则自动创建。cache.addAll(urls) 批量缓存资源列表任一失败则全部回滚。cache.put(request, response) 手动存入请求-响应对常用于动态缓存。caches.match(request) 跨所有缓存仓库匹配请求返回首个匹配的响应。cache.keys() 获取当前缓存仓库中所有请求的列表。典型工作流程Service Worker 场景1安装阶段预缓存资源self.addEventListener(‘install’, (event) {event.waitUntil(caches.open(‘v1’).then(cache cache.addAll([‘/index.html’, ‘/style.css’, ‘/app.js’])));});// 关键点通过 waitUntil 确保缓存完成前 Service Worker 不进入激活状态2拦截请求并返回缓存self.addEventListener(‘fetch’, (event) {event.respondWith(caches.match(event.request).then(cachedResponse cachedResponse || fetch(event.request) // 无缓存则走网络));});// 扩展策略可实现 cache-first优先缓存、network-first优先网络等混合策略2.4 典型应用场景1PWA 离线资源管理预加载核心资源在安装阶段缓存 ShellHTML/CSS/JS确保 首次加载后完全离线可用。动态资源缓存用户访问时缓存图片/数据后续离线时仍可查看历史内容。2自定义缓存策略忽略查询参数通过 new Request(url, { ignoreSearch: true }) 匹配忽略 ?v1.2.3 的资源。版本化缓存按版本号命名缓存仓库如app-v2旧版本缓存需手动清理避免空间浪费。3网络优化降级体验保障网络请求失败时返回缓存内容stale-while-revalidate 模式。减少重复请求对静态资源如字体、第三方库实现跨页面/会话的持久缓存。2.5 注意事项和最佳实践1缓存管理规范必须主动清理旧缓存Service Worker 更新时旧缓存不会自动删除需在 activate 事件中清理self.addEventListener(‘activate’, (event) {event.waitUntil(caches.keys().then(keys Promise.all(keys.filter(k ![‘v1’,‘v2’].includes(k)).map(k caches.delete(k)))));});避免缓存污染仅缓存明确需要离线支持的资源避免无差别缓存导致配额耗尽。2安全与兼容性HTTPS 强制约束非安全上下文HTTP中Chrome 等浏览器完全禁用 Cache API本地开发除外。隐身模式行为数据仅驻留在内存中关闭窗口后自动清除且配额通常 ≤120MB。3与 HTTP 缓存协同双重缓存风险若资源同时被 HTTP 缓存和 Cache Storage 存储浏览器会优先使用 HTTP 缓存因更接近网络层。合理设置 HTTP 头对 Cache Storage 中的资源建议设置 Cache-Control: max-age0避免 HTTP 缓存干扰版本更新。回到顶部三、什么是 Storage buckets注意截至目前Storage Buckets API 仍处于 WICG 提案草案阶段尚未在任何主流浏览器中实现。这意味着它目前无法在生产环境中直接调用仅供了解其思路。Storage Buckets存储桶是 Web 存储技术中一个极具前瞻性的全新存储管理概念。它的核心设计目标是允许开发者将不同类型的数据分组到不同的“存储桶”中并为每个桶配置独立的配额、持久化策略和清理规则。在传统的 Web 存储方式中一个域名Origin下的所有数据如localStorage、IndexedDB、Cache API 等通常混在一起共享浏览器的总存储配额。这导致了两个主要痛点配额竞争和清理策略一刀切。Storage Buckets 通过将数据分类到独立的“桶”中完美解决了上述问题。每个存储桶提供了精细化的控制能力独立配额管理Quota、持久化策略Persisted、耐用性级别Durability。然而在深入了解其强大能力之前必须明确一个关键的现状截至目前Storage Buckets API 仍处于 WICG 提案草案阶段尚未在任何主流浏览器中实现。这意味着它目前无法在生产环境中直接调用现阶段无法依靠标准 Web API 实现模块级的配额硬隔离浏览器也不提供按模块切分配额的粒度但它是未来 Web 存储精细化管理的重要发展方向。如果当前确实需要实现类似“模块数据隔离”的效果建议采用以下替代策略模拟隔离使用 IndexedDB 创建独立的数据库如module-a-db并在键名中强制加上模块标识前缀通过封装读写函数来避免跨模块误读。 物理隔离将模块拆分为不同的子域名如auth.example.com 和 media.example.com利用 origin 的天然隔离获得独立的存储配额。 服务端托管由后端按模块制定存储配额策略如限制 Redis 内存前端仅存储临时句柄或 token。Storage Buckets 描绘了 Web 存储精细化管理的未来蓝图。虽然目前它还只是一个“名字很好听的幻影”但前端开发者可以提前了解其分层存储的设计思想并在当前架构中通过命名空间封装等方式做好数据隔离的准备工作以便在未来 API 落地时能够无缝迁移。回到顶部四、IndexedDB 和 Cache Storage 两者的对比在构建现代 Web 应用尤其是 PWA 和离线优先应用时IndexedDB 和 Cache Storage 是两种最核心的本地存储机制。虽然它们都支持大容量存储和异步操作但其设计初衷和适用场景截然不同。注渐进式 Web 应用PWA是一种使用现代 Web 技术HTML、CSS、JavaScript构建但能提供类似原生应用体验的 Web 应用程序。其架构设计的核心目标是实现跨平台兼容、离线可用、快速加载和原生级交互。三个核心区别1设计初衷与存储对象不同IndexedDB 是浏览器内置的完整 NoSQL 数据库。它主要用于存储结构化的业务数据如JSON 对象、聊天记录、用户文档、配置信息等。它支持复杂的数据模型、多字段索引以及事务ACID非常适合需要频繁增删改查CRUD和条件过滤的场景。Cache Storage缓存存储 API是一个专门用于存储 HTTP 响应的映射表。它主要用于存储静态资源文件如 HTML、CSS、JavaScript、图片等。它通常与 Service Worker 配合使用通过拦截 fetch 请求来实现离线加载和页面秒开。2数据查询与操作方式不同IndexedDB 具备强大的查询能力。开发者可以创建索引使用游标Cursor和键范围Key Range进行复杂的数据检索、排序和过滤。Cache Storage 本质上是一个键值对存储Key-Value Store其“键”是 Request请求“值”是 Response响应。它没有索引功能仅能通过精确的 URL 或自定义的 match 逻辑如忽略查询参数来匹配资源。3底层存储引擎不同IndexedDB 在用户磁盘上使用了真实的数据库引擎。例如基于 Chromium 的浏览器Chrome、Edge使用 LevelDBLSM 树而 Firefox 和 Safari 使用 SQLiteB树这保证了其在处理大型数据集时的高性能和持久性。Cache Storage 则更偏向于文件系统的响应映射专门针对网络请求的缓存与驱逐策略进行了优化。核心特性对比维度 IndexedDB Cache Storage存储内容 结构化对象、JSON、二进制文件Blob 完整的 HTTP 响应Request/Response 对主要用途 离线业务数据、复杂应用状态、用户消息 静态资源JS/CSS/图片、离线应用外壳HTML查询能力 强大支持索引、键范围查询、游标遍历 较弱仅能通过 URL 或自定义规则进行匹配API 类型 事务性、对象存储、异步回调/Promise 基于 Promise 的请求/响应映射存储容量 非常大通常可达设备空闲磁盘的 50%~60% 非常大受浏览器整体配额管理限制典型缓存策略 数据级同步如后台同步队列、增量保存 网络级拦截缓存优先、网络优先、SWR等在实际的 PWA 架构中这两者通常不是“二选一”的关系而是协同工作Service Worker 作为协调器拦截请求。当请求是 /styles.css 或 /app.js 时Service Worker 从 Cache Storage 中返回资源确保应用 UI 瞬间加载。当请求是 /api/user-data 时Service Worker 可能会从 IndexedDB 中读取上次缓存的业务数据返回给用户同时在后台发起网络请求更新 IndexedDB 中的最新数据。回到顶部五、小小的总结本文系统梳理了现代 Web 应用的三大核心存储支柱旨在帮助开发者根据具体场景选择最合适的存储策略IndexedDB结构化数据库定位浏览器内的事务型 NoSQL 数据库。适用存储大量结构化数据如用户文档、聊天记录、离线业务数据。特点容量大可达 GB 级、支持索引查询、事务安全、异步不阻塞 UI。Cache Storage资源缓存定位专用于缓存网络请求/响应对Request/Response。适用实现 PWA 离线访问、静态资源HTML/CSS/JS/图片预加载、自定义网络策略。特点由开发者代码完全控制、独立于 HTTP 缓存头、通常与 Service Worker 配合使用。Storage Buckets存储分区 - 提案阶段定位未来的存储配额与策略管理机制。