rrweb 单仓库(Monorepo)包结构全解析:record、replay、player 与周边工具链
【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrweb
rrweb(record and replay the web)以 npm 单仓库(monorepo)形式组织其全部代码,packages/README.md 是该仓库所有发布包的官方索引,是理解整个项目架构的起点。本文以该文档为主线,逐一剖析 12 个包的职责、依赖关系与源码位置,并给出面向不同使用场景的选型建议,帮助你在阅读源码、参与贡献或进行二次开发时快速定位所需模块。
包总览:一张图看懂 rrweb 的模块划分
根据 packages/README.md,rrweb 单仓库目前包含以下发布包:
| 包名 | 职责定位 | 核心源码入口 |
|---|---|---|
rrweb | 同时包含录制与回放的原始包,已废弃,仅为向后兼容保留 | packages/rrweb/src/entries/record.ts、packages/rrweb/src/entries/replay.ts |
@rrweb/record | 录制相关代码,面向前端页面发布 | packages/record/src/index.ts |
@rrweb/replay | 在 iframe 中重建并回放录制事件 | packages/replay/src/index.ts |
rrweb-player | 基于@rrweb/replay的开箱即用回放 UI | packages/rrweb-player/src/Player.svelte |
rrweb-snapshot | 将 DOM 快照为有状态、可序列化的数据结构,是 FullSnapshot 事件的基础 | packages/rrweb-snapshot/src/snapshot.ts |
@rrweb/types | 各包共享的 TypeScript 类型 | packages/types/src/index.ts |
@rrweb/utils | 各包共享的工具函数 | packages/utils/src/index.ts |
rrdom | 虚拟 DOM 库,用于回放时快速应用 DOM 变更 | packages/rrdom/src/diff.ts |
rrdom-nodejs | rrdom的 Node.js 实现,用于服务端处理 rrweb 数据 | packages/rrdom-nodejs/src/document-nodejs.ts |
rrvideo | 把 rrweb 会话录制转换为视频的 CLI 工具 | packages/rrvideo/src/cli.ts |
web-extension | 录制与回放网页的浏览器扩展 | packages/web-extension/src/content/index.ts |
@rrweb/packer | 网络传输前对事件逐条压缩 | packages/packer/src/pack.ts |
@rrweb/all | 便捷聚合包,包含 record、replay 与 packer,不再包含任何插件 | packages/all/src/index.ts |
插件包(如rrweb-plugin-console-record、rrweb-plugin-network-record等)不在本索引内,另见 插件 API 文档。
核心二包:@rrweb/record与@rrweb/replay的分工
在大多数生产部署中,录制端与回放端位于不同的页面或应用,因此项目将录制与回放拆分为两个独立包:
@rrweb/record:包含 rrweb 全部录制相关代码,面向前端应用/网页发布。其 README 明确说明当前它本质上还是主rrweb包中record函数的包装器,未来所有录制代码会逐步迁移至此(见 packages/record/README.md)。@rrweb/replay:包含回放已录制事件所需的全部代码,但只做基础回放,UI 与控制栏交给使用者自行实现(见 packages/replay/README.md)。
通过 npm 安装并组合使用:
npm install @rrweb/record @rrweb/replayimport { record } from '@rrweb/record'; import { Replayer } from '@rrweb/replay'; import '@rrweb/replay/dist/style.css'; // 录制端:采集事件并交由 emit 回调上传 record({ emit(event) { // send event to server }, });关于record的全部配置项(record options)可参考 guide.md 中的 Getting Started 章节。
浏览器端无打包器(ESM)加载方式
@rrweb/record与@rrweb/replay均提供 CDN 直引的 ESM 产物,适合无构建链路的场景:
<link rel="stylesheet" href="https://cdn.rrweb.com/replay/current/dist/style.css" /> <script type="module"> import { record } from 'https://cdn.rrweb.com/record/current/dist/record.js'; import { Replayer } from 'https://cdn.rrweb.com/replay/current/dist/replay.js'; </script>其中current指向最新稳定版;生产环境建议固定不可变版本号,例如https://cdn.rrweb.com/record/2.0.0/dist/record.js。两包还额外提供 UMD 兼容产物(record.umd.cjs/replay.umd.cjs),对应的全局变量分别为rrwebRecord与rrwebReplay,仅用于不支持模块的老环境。
被拆分的原包rrweb:为什么被废弃
原rrweb包同时包含 record 与 replay 两份逻辑,现已标记为Deprecated,仅为了向后兼容而保留。其 README 明确指出:
New projects should depend on
@rrweb/recordand@rrweb/replaydirectly, or use@rrweb/allfor a single convenience import.
从源码结构看,该包的 packages/rrweb/src/record 与 packages/rrweb/src/replay 目录仍然是 record 与 replay 两类 TypeScript 代码的实际所在(packages/rrweb/README.md 的 Dev Note 也说明这一点),这些代码最终会被重构迁移到各自独立包中。也就是说,当前@rrweb/record与@rrweb/replay的入口是对旧包内实现的再导出。
对于仍在使用旧包的项目,其安装与使用方式为:
npm install rrwebimport { record, Replayer } from 'rrweb'; import 'rrweb/dist/style.css';开箱即用的回放 UI:rrweb-player
如果不想自己实现回放控制栏,可以直接使用rrweb-player——它基于@rrweb/replay,用 Svelte UI 框架封装出了播放/暂停控制与时间线,官方云控制台(app.rrweb.com)使用的正是这一回放器。它与new Replayer()的关键区别在于:后者只负责在 iframe 内渲染重建事件流,前者在此基础上提供完整 UI(见 packages/rrweb-player/README.md)。
npm install rrweb-playerimport rrwebPlayer from 'rrweb-player'; import 'rrweb-player/dist/style.css'; new rrwebPlayer({ target: document.body, // customizable root element props: { events, }, });其组件级配置项如下表:
| key | 默认值 | 说明 |
|---|---|---|
events | [] | 用于回放的事件数组 |
width | 1024 | 回放器宽度 |
height | 576 | 回放器高度 |
maxScale | 1 | 回放器最大缩放比例(1 = 100%,设为 0 表示不限) |
autoPlay | true | 是否自动播放 |
speed | 1 | 默认播放速度 |
speedOption | [1, 2, 4, 8] | UI 中可选的速度档位 |
showController | true | 是否显示控制栏 UI |
tags | {} | 以键值对自定义 custom events 的样式 |
inactiveColor | #D4D4D4 | 进度条中非活跃时段的指示颜色(合法 CSS 颜色字符串) |
... | - | 其余参数全部透传给底层Replayer的配置 |
此外,rrwebPlayer 组件实例暴露了addEventListener、addEvent、getMetaData()(返回startTime/endTime/totalTime)、getReplayer()、getMirror()等方法,方便在外部控制回放流程。
序列化基础:rrweb-snapshot
rrweb-snapshot是所有事件数据格式的基石:它将 DOM 快照为有状态、可序列化的数据结构,并提供反向重建 DOM 的能力,是录制中 FullSnapshot 事件的基础(见 packages/rrweb-snapshot/README.md)。其公开 API 包括:
snapshot:遍历 DOM 并返回可表示当前 DOM视图的序列化结构。快照过程中会做五件事:- 把部分 DOM 状态内联进 HTML 属性(如
HTMLInputElement的 value); - 将
script标签转为noscript,避免脚本被执行; - 尝试内联样式表,保证本地样式可用;
- 将 href、src、CSS 中的相对路径改为绝对路径;
- 为每个 Node 分配 id,并在快照完成后返回 id 节点映射表。
- 把部分 DOM 状态内联进 HTML 属性(如
rebuild:根据快照构建 DOM。在浏览器环境中,rebuild()是底层 API,除非传入UNSAFE_allowUnprotectedRebuild: true,否则要求使用rebuildIntoSandboxedIframe()创建的 document——不可信任的回放数据绝不能直接重建到顶层 document 或调用方自建的 iframe document 中。重建过程中会:为 Element 添加data-rrid属性、创建额外 DOM 节点放置内联 CSS 与部分状态、为含额外子 DOM 的节点添加data-extra-child-index属性。rebuildIntoSandboxedIframe:浏览器环境推荐使用的安全入口,需要显式传入root元素:const { iframe, node } = rebuildIntoSandboxedIframe(snapshot, { root: document.body, cache, mirror, });需要自行管理 iframe 时,可先用
createSandboxedIframe()创建,再调用rebuild()。serializeNodeWithId:将单个节点序列化为带 id 的快照格式。buildNodeWithSN:从序列化节点构建 DOM,并将序列化信息存入mirror.getMeta(node)。
这些安全约定对应仓库中的 sandbox 设计文档 与 ADR:require sandboxed browser rebuilds。
共享基础设施:@rrweb/types与@rrweb/utils
@rrweb/types:提供各包共享的 TypeScript 类型。rrweb 大量依赖 TS 类型来保证正确性并定义包间数据 API,主事件类型Event的介绍见 事件文档。@rrweb/utils:提供各包共享的工具函数,具体实现见 packages/utils/src/index.ts。
这两个包都只承担基础能力,不依赖业务逻辑,是其他包的公共依赖。
回放性能引擎:rrdom与rrdom-nodejs
rrdom:一个独立的虚拟 DOM 库,用于回放时快速应用 DOM 变更(mutation)。rrweb 借助它在拖动时间轴 seek 时优化回放性能——不是逐条重放增量,而是对虚拟 DOM 树打补丁(patch)到真实 DOM(见 packages/rrdom/README.md)。其核心 diff 逻辑在 packages/rrdom/src/diff.ts。rrdom-nodejs:rrdom的 Node.js 实现,用于服务端处理 rrweb 数据——可以在 Node 环境中回放并检查录制的用户交互,适合服务端渲染、数据校验或测试场景(见 packages/rrdom-nodejs/README.md)。
离线与周边工具:rrvideo与web-extension
rrvideo:把 rrweb 录制的会话(JSON 格式事件文件)转换为视频的 CLI 工具,安装与使用方式(详见 packages/rrvideo/README.md):npm i -g rrvideo rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_FILE命令会在当前目录输出
rrvideo-output.webm文件。另提供 中文文档 与示例配置 packages/rrvideo/rrvideo.config.example.json。web-extension:提供录制与回放网页的浏览器扩展,支持 Chrome 与 Firefox 构建(packages/web-extension/README.md):# build for chrome yarn build:chrome # build for firefox yarn build:firefox
压缩与聚合:@rrweb/packer与@rrweb/all
@rrweb/packer:在前端完成网络传输前的逐事件压缩,基于fflate的 zlib 压缩,每个 rrweb 事件在产出时被单独压缩。录制端需要引入编码器,约增加 17KB(minified,gzip 后更小)包体;回放端的解压由独立的@rrweb/packer/unpack入口处理(见 packages/packer/README.md)。工作原理详见 存储优化 recipe。@rrweb/all:便捷聚合包,包含rrweb、@rrweb/record、@rrweb/replay、@rrweb/packer,适合 demo、工具类或希望单一依赖导入的场景;它与旧rrweb包的作用类似,但不再包含任何插件(见 packages/all/README.md)。
npm install @rrweb/allimport { record, Replayer, pack, unpack } from '@rrweb/all'; import '@rrweb/all/dist/style.css';选型指南:不同场景下如何选择包
综合 packages/README.md、packages/rrweb/README.md 与 packages/all/README.md 的说明,选择逻辑可以归纳为:
| 使用场景 | 推荐包组合 |
|---|---|
| 大多数新应用(录制与回放分别部署) | @rrweb/record+@rrweb/replay |
| 需要开箱即用的回放控制 UI | @rrweb/replay+rrweb-player |
| 单一依赖同时拿到 record、replay 与 packer | @rrweb/all |
| 兼容旧项目 | rrweb(已废弃,仅向后兼容) |
| 服务端处理/回放 rrweb 数据 | rrdom-nodejs |
| 把录制转成视频文件 | rrvideo |
| 浏览器扩展形态的录制/回放 | web-extension |
| 传输前压缩事件体积 | @rrweb/packer |
如何继续深入
- 录制与回放的完整使用教程与全部配置项:阅读 guide.md(含 Getting Started、record options 与 replay options)。
- 事件数据结构详解:阅读 事件文档。
- 录制原理(observer 架构):阅读 observer.md。
- 回放原理:阅读 replay.md。
- 快照与序列化细节:阅读 serialization.md。
- 插件体系:阅读 插件 API 文档 与 插件 recipe。
- 参与贡献:参考 CONTRIBUTING.md,注意当前 record 与 replay 的 PR 仍主要在
rrweb包内提交(见 packages/rrweb/README.md 的 Dev Note)。
【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrweb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考