RxDB SharedWorker RxStorage 实战指南:让多个标签页共享同一个数据库进程
数据库NoSQL嵌入式数据库实时数据库【免费下载链接】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点击查看免费下载SharedWorker RxStorage 是 RxDB 的 Premium 插件 之一它基于浏览器的 SharedWorker API 运行在一个独立的 JavaScript 进程中。与普通 WebWorker RxStorage 不同SharedWorker 在打开多个浏览器标签页时也只会创建一次从而可以在存储层之上做大量性能优化——因为存储本身不再需要处理多个并发的数据库连接。阅读本文后你将掌握 SharedWorker RxStorage 的完整接入方式、参数含义、预构建 worker 的使用方法以及如何在 worker 内部高效运行复制replication。为什么选择 SharedWorker与 WebWorker 的核心差异在浏览器中RxDB 的数据存储层RxStorage默认运行在主线程上复杂的读写与查询会与 UI 渲染争抢 CPU。Worker 系列插件的思路是把存储放进独立进程把 CPU 负载从主线程移走。二者的差异在于WebWorker每个标签页各自创建一个 worker 进程每个标签页各自持有一个 IndexedDB 连接数据变更需要通过事件在标签页间传播SharedWorker同一 origin 下的所有标签页共享唯一一个worker 实例数据库只维持一份存储实例。从 RxStorage 总览 的定位看SharedWorker RxStorage 是一个包装器wrapper它本身不存数据而是把任何实现了 RxStorage 接口的底层存储如 IndexedDB包进 worker 进程。因为所有标签页共享同一进程数据库实例可以被去重多个标签页之间也不再需要为每个连接复制一份完整的存储状态。这一设计在源码层面有直接印证exposeRxStorageRemote在远端维护了一个instanceByFullName映射以databaseName|collectionName|schemaVersion为键多个端口Port连接同一存储实例时会复用同一个RxStorageInstance并把各自的connectionId记录在connectionIds集合中见 src/plugins/storage-remote/remote.ts。注释中明确写道这在很多环境下都有意义比如 Electron 的主进程为多个渲染进程保存存储SharedWorker 也是如此。 只有最后一个端口关闭时connectionIds.size 1底层实例才会真正被 closeremote.ts。快速上手两端配置SharedWorker RxStorage 的使用分两部分worker 进程端暴露存储和主进程端消费存储。在 SharedWorker 进程中暴露存储worker 进程的 JavaScript 文件里用exposeWorkerRxStorage()把任意 RxStorage 实现包装起来// shared-worker.ts import { exposeWorkerRxStorage } from rxdb-premium/plugins/storage-worker; import { getRxStorageIndexedDB } from rxdb-premium/plugins/storage-indexeddb; exposeWorkerRxStorage({ /** * 你可以把任何 RxStorage 接口的实现包装进 worker。 * 这里我们使用 IndexedDB RxStorage。 */ storage: getRxStorageIndexedDB() });exposeWorkerRxStorage会检测自己运行在普通 Worker 还是 SharedWorker 环境中并自动暴露正确的消息端点messaging endpoints——这也是为什么任何合法的worker.js文件既能用于普通 Worker也能用于 SharedWorker。在主进程中创建数据库主线程侧通过getRxStorageSharedWorker()创建数据库它接收一个包含workerInput与可选workerOptions的对象import { createRxDatabase } from rxdb; import { getRxStorageSharedWorker } from rxdb-premium/plugins/storage-worker; import { getRxStorageIndexedDB } from rxdb/plugins/storage-indexeddb; const database await createRxDatabase({ name: mydatabase, storage: getRxStorageSharedWorker( { /** * 任何可以作为 SharedWorker 构造器thread.js参数的值。 * 大多数情况下这里放 shared-worker.js 文件的路径。 */ workerInput: path/to/shared-worker.js, /** * 可选worker 的选项。 */ workerOptions: { type: module, credentials: omit, extendedLifetime: true } } ) });注意主进程侧的getRxStorageSharedWorker来自rxdb-premium/plugins/storage-worker与普通 Worker 插件同一模块而示例中getRxStorageIndexedDB的导入路径来自rxdb/plugins/storage-indexeddb请以你实际安装的包与版本为准。workerInput 与 workerOptions 参数说明workerInput必填。任何能传给 SharedWorker 构造器的值thread.js 兼容。最常见的就是shared-worker.js的 URL 路径也可以传入一个返回SharedWorker实例的函数见下文传入 SharedWorker 实例。workerOptions可选透传给 worker 的选项对象typemodule表示以 ES Module 方式加载 worker 文件也可以设为classiccredentials加载 worker 模块时的凭据模式omit表示不发送凭据也可设为same-origin或includeextendedLifetimeSharedWorker 专属选项。开启后 worker 不会因为所有标签页关闭而立即销毁从而在下一次访问时避免重新初始化的开销。该选项的支持在 17.0.0 发布说明 中作为新增能力被记录ADD使用 SharedWorker 时支持extendedLifetime。使用预构建的 workershared-worker.js必须是一个自包含的 JavaScript 文件——所有依赖都要打进同一个 bundle 里。为了省去打包的麻烦RxDB 直接提供了开箱即用的预构建 worker 文件安装 RxDB Premium 插件在node_modules/rxdb-premium/dist/workers目录下找到预构建文件把它们复制到 Web 服务器可以静态托管的路径下在创建RxDatabase时传入该路径import { createRxDatabase } from rxdb; import { getRxStorageSharedWorker } from rxdb-premium/plugins/storage-worker; const database await createRxDatabase({ name: mydatabase, storage: getRxStorageSharedWorker( { /** * 从 node_modules/rxdb-premium/dist/workers 复制出的文件 * 在 Web 服务器上可被访问到的路径。 */ workerInput: /indexeddb.shared-worker.js } ) });任何合法的worker.js文件都可以同时用于普通 Worker 和 SharedWorker因为exposeWorkerRxStorage会自动适配运行环境。因此在预构建产物中同一个文件既可作为workerInput传给getRxStorageWorker也可传给getRxStorageSharedWorker。构建自定义 worker如果要构建自己的worker.js推荐使用 webpack 打包配置可参考 Worker RxStorage 文档 中Building a custom worker一节给出的、与官方预构建 worker 相同的 webpack 配置。核心要点如下完整配置见 docs-src/docs/rx-storage-worker.mdtarget: webworker确保产物面向 worker 环境entry 指向你的 worker 入口文件如my-custom-worker.ts内部调用exposeWorkerRxStorage({ storage: getRxStorageIndexedDB() })通过 babel-loader 处理 TypeScript/TSXresolve.extensions覆盖.tsx/.ts/.js/.mjs/.mtsmode: production并用 TerserPlugin 压缩、去除注释生成自包含的 bundle。传入 SharedWorker 实例除了直接给 URLworkerInput也可以是一个返回新SharedWorker实例的函数。这在你有自定义 worker 文件、并希望通过构建工具动态导入时最常用用法与 Worker Storage 的 workerInput 完全一致const storage getRxStorageSharedWorker({ workerInput: () new SharedWorker( new URL(./my-custom.shared-worker, import.meta.url) ) });例如在 Angular 等由打包器处理 worker 构建的环境中可以单独维护一个my-custom.worker.ts内含exposeWorkerRxStorage再用new URL(..., import.meta.url)动态导入打包器会自动产出对应的 worker 产物。设置 multiInstance: false当你能确定 RxDatabase只在 SharedWorker 内部创建时可以考虑设置multiInstance: false从而避免跨 JavaScript realm主线程与 worker 之间发送变更事件进一步提升性能。注意如果你在另一个 realm 也创建了同一个存储例如同一个 RxDatabase 既在 SharedWorker 内、又在主线程上各创建了一份就不要设置multiInstance: false。在 SharedWorker 中运行复制Replication使用 SharedWorker RxStorage 时官方推荐把复制replication放在 worker 内部运行这是性能最优的做法。具体方式是在 worker 里再打开一个 RxDatabase 并启动复制// shared-worker.ts import { exposeWorkerRxStorage } from rxdb-premium/plugins/storage-worker; import { getRxStorageIndexedDB } from rxdb-premium/plugins/storage-indexeddb; import { createRxDatabase, addRxPlugin } from rxdb; import { RxDBReplicationGraphQLPlugin } from rxdb/plugins/replication-graphql; addRxPlugin(RxDBReplicationGraphQLPlugin); const baseStorage getRxStorageIndexedDB(); // 先把 RxStorage 暴露给外部主线程 exposeWorkerRxStorage({ storage: baseStorage }); /** * 然后在 worker 内部创建常规的 RxDatabase 和 RxCollections * 并在此启动复制。 */ const database await createRxDatabase({ name: mydatabase, storage: baseStorage }); await database.addCollections({ humans: {/* ... */} }); const replicationState database.humans.syncGraphQL({/* ... */});这样网络 I/O、协议解析等复制负担都发生在 worker 进程主线程只接收复制结果产生的变更事件UI 完全不被阻塞。如果你不关心性能也可以在主线程启动复制但绝不能在主线程和 worker 里同时运行复制否则会产生重复的双向同步与冲突。限制SharedWorker API 在部分移动浏览器中不可用可参考 caniuse 的 sharedworkers 兼容性数据。在决定使用该插件前请先确认目标浏览器环境对 SharedWorker 的支持情况。常见问题可以把 SharedWorker RxStorage 用在 Service Worker 上吗不能。Service Worker 与 Shared Worker 不是一回事你可以在 ServiceWorker 内部使用 RxDB但不能把 ServiceWorker 当作一个被外部 RxDatabase 实例访问的 RxStorage。SharedWorker 是如何帮助多个标签页同步状态的SharedWorkerAPI 会为同一 origin 下的所有标签页生成恰好一个共享的隔离后台线程。当 RxDB 挂载到这个 Shared Worker 上后就不再需要每个标签页各自维护冗余的 IndexedDB 连接和昂贵的 JSON 序列化——只有后台 worker 执行资源密集的 CRUD 操作再把极轻量的结果差分differentials同时广播给所有被动监听的 UI 标签页。这正是 SharedWorker 相比普通 WebWorker 在多标签页场景下性能更好的根本原因也解释了为什么浏览器端官方推荐优先使用 SharedWorker 而非 WebWorker见 Worker RxStorage 文档 开头的说明。赞分享数据库NoSQL嵌入式数据库实时数据库【免费下载链接】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点击查看免费下载相关推荐RxDB 领导者选举Leader Election实战指南让浏览器多标签页只保留一个数据连接RxDB 领导者选举Leader Election实战指南让浏览器多标签页只保留一个数据连接 本文围绕 RxDB 的 leader election 插件数据库NoSQL嵌入式数据库实时数据库go-json实战从零构建高性能JSON API的完整教程go json实战从零构建高性能JSON API的完整教程 在Go语言开发中JSON处理性能往往是API服务的关键瓶颈。 go json 作为一款兼容 enAI工程师的认知地图从基础模型到生产级应用的完整路径AI工程师的认知地图从基础模型到生产级应用的完整路径 在AI技术快速迭代的今天将基础模型转化为可靠的生产级应用已成为每个AI工程师必须掌握的核心能力。《AI人工智能大模型文档上一篇3分钟上手JWT认证tymon/jwt-auth从安装到实战全攻略下一篇tsParticles Interactivity 交互配置详解detectsOn、events 与 modes 的完整用法与源码原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

ASTM E45钢中非金属夹杂物评定:从形状分类到工程实践

ASTM E45钢中非金属夹杂物评定:从形状分类到工程实践

简介:ASTM E45夹杂物分析标准中文版面向钢铁冶金、质量检测与材料科学领域的从业者,系统规定了锻钢中非金属夹杂物的宏观与显微评定方法,可用于判断夹杂物的种类、形状和数量,为钢材质量控制和工艺优化提供依据。压缩包内为1个PDF…

2026/9/20 2:58:08 阅读更多 →
产消者能量共享的非合作博弈与ADMM分布式优化实战

产消者能量共享的非合作博弈与ADMM分布式优化实战

1. 场景解析:为什么多产消者能量共享值得做做这个项目之前,我第一反应是:现在的电力系统研究,早就不是单纯“发电厂—电网—用户”这种单向流动的模型了。分布式光伏、小型风机、储能、电动汽车这些资源在用户侧铺开之后&#xff…

2026/9/20 2:58:08 阅读更多 →
MiniMax M3 转发,CC Switch 图形点选教程这次用 TaoToken 走通

MiniMax M3 转发,CC Switch 图形点选教程这次用 TaoToken 走通

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:58:08 阅读更多 →

最新新闻

C盘被 odis_download_dest 塞满?CAD与诊断软件缓存堆积清理全攻略

C盘被 odis_download_dest 塞满?CAD与诊断软件缓存堆积清理全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 4:14:02 阅读更多 →
Codex 历史会话列表消失?数据恢复与索引重建指南

Codex 历史会话列表消失?数据恢复与索引重建指南

1. 会话没丢,只是列表不见了:问题到底出在哪Codex 用久了,最让人心里一紧的场景不是模型报错,而是某天打开 CLI,发现历史会话列表空了。那一瞬间脑子里闪过的念头通常是“完了,记录被清了”。但实际情况往往…

2026/9/20 4:14:02 阅读更多 →
流媒体测试地址全解析:RTSP、RTMP、M3U8、FLV、MP4实测与本地搭建

流媒体测试地址全解析:RTSP、RTMP、M3U8、FLV、MP4实测与本地搭建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 4:14:02 阅读更多 →
IsaacLab VSCode调试配置踩坑记:3步解决ModuleNotFoundError报错

IsaacLab VSCode调试配置踩坑记:3步解决ModuleNotFoundError报错

IsaacLab VSCode调试配置踩坑记:3步解决ModuleNotFoundError报错 【免费下载链接】IsaacLab Unified framework for robot learning with multi-physics/renderer support 项目地址: https://gitcode.com/GitHub_Trending/is/IsaacLab 概览:在Isa…

2026/9/20 4:14:02 阅读更多 →
IDEA集成Claude Code与Codex:AI编程代理实战指南

IDEA集成Claude Code与Codex:AI编程代理实战指南

1. 为什么偏偏是 IDEA:IDE 与 AI 编程助手的合体逻辑先说结论:Claude Code 和 Codex 这类终端型 AI 编程工具,单独用只是“半个神器”,真正让它们起飞的关键,是把它们塞进 IDEA 这个“老巢”里。我在过去大半年里&…

2026/9/20 4:14:02 阅读更多 →
RTX 50 显卡跑不动 IsaacLab?版本冲突根因与两条快速修复路径全解

RTX 50 显卡跑不动 IsaacLab?版本冲突根因与两条快速修复路径全解

RTX 50 显卡跑不动 IsaacLab?版本冲突根因与两条快速修复路径全解 【免费下载链接】IsaacLab Unified framework for robot learning with multi-physics/renderer support 项目地址: https://gitcode.com/GitHub_Trending/is/IsaacLab 你刚把 IsaacLab 装完…

2026/9/20 4:13:02 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →