
将 TanStack DB 持久化到 IndexedDB 与 OPFS基于 RxDB 存储层的浏览器持久化配置实战【免费下载链接】rxdbThe local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/项目地址: https://gitcode.com/gh_mirrors/rx/rxdbTanStack DB 默认把所有 collection 数据保存在内存中页面刷新即丢失持久化职责由你选择的 collection 实现来承担。官方tanstack/rxdb-db-collection包把 RxDB一款存储引擎可插拔的 local-first NoSQL 数据库置于 TanStack DB collection 之下于是如何持久化 TanStack DB就变成了在 localStorage、IndexedDB 与 OPFS 之间的配置选择。本文以 persist-tanstack-db-indexeddb.md 为主体完整介绍浏览器端各存储选项的取舍、一套可运行的 localStorage 持久化示例并展示切换到 IndexedDB 或 OPFS 时只需替换一行storage:配置的做法。读完本文你将掌握 TanStack DB RxDB 组合在浏览器端的全部持久化方案与切换技巧。为什么 TanStack DB 需要一层存储TanStack DB 是一个内存型响应式客户端 store。实时查询live queries与乐观更新optimistic mutations都作用在 JavaScript 内存中的数据上这正是它们即时响应的原因。而持久化被明确委托给了 collection 类型RxDB collection 用真正的数据库来填补这一角色——对 TanStack DB collection 的每次写入都会持久化到对应的 RxCollection下一次页面加载时collection 会从磁盘恢复自身状态。RxDB 本身并不关心磁盘具体是什么。所有数据都经由 RxStorage 接口流动你在创建数据库时选定具体实现。TanStack DB 代码永远不会直接触碰存储层这正是切换存储只是改配置、而不是重写代码的根本原因。从源码结构看这一抽象非常直观例如 getRxStorageLocalstorage 返回一个实现RxStorage接口的RxStorageLocalstorage实例而createRxDatabase只依赖该接口。存储层的内部细节如 RxStorageInstanceLocalstorage 把整个状态以字符串化 JSON 存进 localStorage对上层完全透明。TanStack DB 在浏览器中的存储选项对浏览器应用而言有四类存储值得关注两类免费、两类属于 RxDB Premium 商业插件。存储价格基于适用场景LocalStorage 存储免费localStorage API中小数据集、最简配置Dexie.js 存储免费IndexedDB无 Premium 权限的较大数据集IndexedDB 存储 付费IndexedDB生产应用、最低延迟、最小构建体积OPFS 存储 付费Origin Private File System大数据集、最快查询LocalStorage 存储免费基于 localStorage 的存储是起步阶段的推荐默认项无额外依赖、构建体积小、小数据集读写很快性能对比见 localstorage-indexeddb-cookies-opfs-sqlite-wasm.md 的 performance-comparison 章节。其代价是浏览器通常把 localStorage 限制在每域名约 5 MB且访问是主线程上的同步操作。对 todo 应用、设置存储或原型来说这完全够用问题始于数据集增长到几千条文档之后。源码层面localStorage 存储把全部状态按 key 分桶存放——docsKey文档、attachmentsKey附件、changestreamStorageKey变更流、indexesKey索引见 rx-storage-instance-localstorage.ts。它还借助浏览器原生storage事件实现跨标签页的变更广播storageEventStream这也侧面说明它天然适配多标签页场景。Dexie.js 存储免费Dexie.js 存储通过 Dexie.js 封装库把数据写入 IndexedDB。IndexedDB 没有固定的 5 MB 上限因此它是无 Premium 权限、但数据集较大时的免费选择也支持使用 Dexie.js 生态的 addons。它的代价包括控制台会打印一条指向 Premium 存储的提示信息查询性能落后于 Premium 版 IndexedDB 存储。IndexedDB 存储 Premium 版 IndexedDB 存储直接构建在原生 IndexedDB 之上不依赖任何封装库。相比 Dexie.js 存储它的读写更快、构建体积最多可减少约36%并运行在类似 SQLite 的 WALWrite-Ahead Logging模式下以获得更快写入。在浏览器存储中它的写入/读取延迟最小、首次页面加载最快是多数生产应用的默认选择。需要说明的是这些性能结论以当前仓库文档 rx-storage-indexeddb.md 与 rx-storage-performance.md 的记载为准。OPFS 存储 Premium 版 OPFS 存储把数据写入Origin Private File SystemOPFS——一项让 Web 应用获得沙箱化、按源隔离的虚拟文件系统并提供字节级文件访问的浏览器 API。由于它操作的是二进制文件而非对象存储复杂查询下的读取可比 IndexedDB 快最多 4 倍。OPFS 的高速同步方法只存在于 WebWorker 中因此该存储默认运行在 worker 内顺带把数据库工作移出主线程。当 TanStack DB collection 持有超过10k条文档时OPFS 是更优选择完整数据见 rx-storage-performance.md。持久化 TanStack DB collection可运行示例下面以免费的 localStorage 存储为例演示完整链路。集成基础双循环架构、rxdbCollectionOptions配置项等见 TanStack DB RxDB 集成概述此处只保留必要部分。安装依赖npm install rxdb rxjs tanstack/react-db tanstack/rxdb-db-collectionTanStack DB 还提供 Vue、Solid、Svelte、Angular 的官方绑定。由于rxdbCollectionOptions()面向框架无关的createCollection()APIRxDB collection 与所有官方框架绑定均兼容——例如 React 之外只需把useLiveQuery的导入换成tanstack/vue-db。创建持久化的 RxDatabaseimport { createRxDatabase } from rxdb/plugins/core; import { getRxStorageLocalstorage } from rxdb/plugins/storage-localstorage; const db await createRxDatabase({ name: todosdb, // 这一行决定了你的 TanStack DB 数据被持久化到哪里。 storage: getRxStorageLocalstorage() }); await db.addCollections({ todos: { schema: { title: todos, version: 0, type: object, primaryKey: id, properties: { id: { type: string, maxLength: 100 }, text: { type: string }, completed: { type: boolean } }, required: [id, text, completed] } } });schema是标准 RxDB JSON SchemaprimaryKey声明主键字段maxLength限制索引键长度required强制必填字段。RxDB 会在写入时做模式校验校验失败会导致写入被拒绝并回滚。包装成 TanStack DB collectionimport { createCollection } from tanstack/react-db; import { rxdbCollectionOptions } from tanstack/rxdb-db-collection; const todosCollection createCollection( rxdbCollectionOptions({ rxCollection: db.todos }) );todosCollection从此就是一个标准的 TanStack DB collection首次加载时从磁盘恢复初始状态之后持续跟随 RxDB 的变化。rxdbCollectionOptions()还支持若干可选参数idcollection 唯一标识、schemaTanStack DB 侧的 Standard Schema 校验由于 RxDB 已按 JSON Schema 校验通常仅用于统一错误处理、startSync默认true是否立即开始摄取 RxDB 数据、syncBatchSize默认1000初始加载时每批拉取的文档数只影响初始加载后续变更通过 RxDB 变更流逐条流入。查询、变更并刷新验证import { useLiveQuery, eq } from tanstack/react-db; function OpenTodos() { const { data } useLiveQuery((q) q .from({ todo: todosCollection }) .where(({ todo }) eq(todo.completed, false)) ); return div{data.length} open todos/div; } // 写入即时作用于内存并由 RxDB 持久化。 todosCollection.insert({ id: todo-1, text: buy milk, completed: false });写入在内存中即时生效并后台持久化到 RxDB若持久化失败如模式校验错误TanStack DB 会回滚乐观状态。此时刷新页面collection 会从存储中恢复状态todo-1依然存在。这正是TanStack DB 持久化的意义所在——内存 store 之所以能扛过刷新是因为 RxDB 在磁盘上拥有一份持久副本。从源码看TanStack DB collection 的写入最终走 RxDB 的批量写方法insert 对应bulkUpsert()、update 对应incrementalPatch()、delete 对应bulkRemove()详见 rxdb-collection-for-tanstack-db.md 的 Configuration Options 章节。切换到 IndexedDB 或 OPFS上面的应用代码完全不需要改动只需替换导入语句和createRxDatabase()里的storage:一行。使用免费的 Dexie.js 存储底层即 IndexedDBimport { getRxStorageDexie } from rxdb/plugins/storage-dexie; const db await createRxDatabase({ name: todosdb, storage: getRxStorageDexie() });使用 Premium 版 IndexedDB 存储 import { getRxStorageIndexedDB } from rxdb-premium/plugins/storage-indexeddb; const db await createRxDatabase({ name: todosdb, storage: getRxStorageIndexedDB() });使用 Premium 版 OPFS 存储 ——它通过 worker 存储运行在 WebWorker 内import { getRxStorageWorker } from rxdb-premium/plugins/storage-worker; const db await createRxDatabase({ name: todosdb, storage: getRxStorageWorker({ // 该文件必须由你的 Web 服务器静态托管。 workerInput: node_modules/rxdb-premium/dist/workers/opfs.worker.js }) });如果想省去 worker 部署rxdb-premium/plugins/storage-opfs导出的getRxStorageOPFSMainThread()可用异步 OPFS API 在主线程运行 OPFS。两种变体的性能差异worker 对顺序读更快主线程对批量插入因免去消息序列化开销可能反而更快对比见 rx-storage-opfs.md 的 using-opfs-in-the-main-thread-instead-of-a-worker 章节建议针对实际用例分别实测。需要注意新的存储从空开始。如果在已有用户数据的应用中切换存储请先用 storage migration 插件 把既有文档迁移过去。该插件会按批次batchSize示例为 500把旧存储的文档复制进新数据库它只迁移调用migrateStorage()时新数据库中已定义的 collection并且会丢弃已删除文档同时官方明确警告不要在存储迁移过程中同时修改 schema应先迁移存储、再跑 schema 迁移见 migration-storage.md。TanStack DB 自带持久化方案对比TanStack DB 也自带浏览器持久化tanstack/browser-db-sqlite-persistence适配器通过 wa-sqlite 把 collection 持久化到编译为 WebAssembly 的 SQLite。如果需求仅仅是collection 在浏览器刷新后存活该适配器完全够用无需引入 RxDB。而 RxDB collection 更适合持久化只是第一步的场景多种存储同一套代码路径横跨 localStorage、IndexedDB、OPFS 与原生平台的 SQLite 存储按环境选择。复制同步RxDB 的 Sync Engine 可把持久化数据与任意后端同步包括 offline-first 行为。加密数据落盘前可先 加密本地数据。多标签页所有标签页共享同一份持久存储并通过 leader election 保证复制只在一个标签页运行而不是每个标签页各自持有一份状态。FAQTanStack DB 默认会把数据持久化到 IndexedDB 吗不会。TanStack DB collection 是内存型的页面刷新即丢失状态。持久化来自 collection 实现使用RxDB collection时通过配置对应的 RxStorage即可持久化到 localStorage、IndexedDB 或 OPFS。我可以免费把 TanStack DB 持久化到 IndexedDB 吗可以。免费的Dexie.js 存储会把 TanStack DB 数据存入 IndexedDB。Premium 版 IndexedDB 存储 更快、构建体积更小但获得可靠的 IndexedDB 持久化并不需要它。对 TanStack DB 存储而言OPFS 比 IndexedDB 快吗大数据集上的读取是的。OPFS 存储基于二进制文件工作读取可比 IndexedDB 快最多 4 倍而 IndexedDB 存储的首次页面加载更快、构建体积更小。因此当 collection 超过10k条文档时OPFS 才真正划算。切换 RxDB 存储会丢数据吗不会丢但数据不会自己搬过去。旧存储保留文档、新存储从空开始。用storage migration 插件执行一次迁移把既有文档复制进新存储再发布新配置即可。存储选择会改变我的 TanStack DB 代码吗不会。TanStack DB 面向 RxCollection 编程RxCollection 面向你配置的任意RxStorage编程。查询、变更与实时更新在任何存储上行为一致——切换存储是配置变更不是重写。延伸阅读完整的集成指南见 TanStack DB RxDB 集成概述。从 RxDB 快速开始 起步。在 RxStorage 总览 与 性能对比页 横向比较所有存储。用同一套代码在原生平台使用 SQLite 存储。在持久化数据之上叠加 后端同步。【免费下载链接】rxdbThe local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/项目地址: https://gitcode.com/gh_mirrors/rx/rxdb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考