rrweb 事件顺序 ID 插件实战:用@rrweb/rrweb-plugin-sequential-id-record为录制事件打上连续编号
【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrweb
本文介绍 rrweb 官方插件@rrweb/rrweb-plugin-sequential-id-record(顺序 ID 录制插件)的安装、配置与底层原理。它通过与@rrweb/rrweb-plugin-sequential-id-replay配合使用,为录制阶段产出的每一个事件附加一个从 1 开始递增的序号,并在回放阶段校验事件顺序是否完整、是否发生丢帧或乱序。读完本文,你将掌握如何为事件流添加稳定的顺序标识、如何在回放端做一致性校验,以及该机制在事件关联与调试中的典型用法。
插件定位:与回放端插件成对使用
rrweb 的录制与回放默认依赖事件内的timestamp来排序与驱动时间轴,但时间戳并非严格单调,且无法直接表达“事件流中第 N 个事件”这一语义。顺序 ID 插件正是为解决这一问题而生:
- 录制端(本文主角):在每个事件被 emit 之前,往事件对象上写入一个全局递增的整数 ID;
- 回放端:读取该 ID,检查事件到达顺序是否为 1、2、3…… 的连续递增序列,一旦发现跳跃、重复或缺失,立即在控制台输出错误信息。
官方文档明确要求两个插件“成对使用”,详见 @rrweb/rrweb-plugin-sequential-id-replay 的 README。完整的 rrweb 使用说明见仓库根目录的 guide.md,插件的通用机制(RecordPlugin/ReplayPlugin接口)见 插件 API 文档。
安装
与 rrweb 其它插件一样,通过 npm 安装即可:
npm install @rrweb/rrweb-plugin-sequential-id-record从 package.json 可以看到,该包要求rrweb ^2.1.1作为 peerDependency,同时声明了 UMD(main/unpkg/jsdelivr)与 ESM(module)两种产物,因此既适合打包器内的import使用,也适合 CDN 直接引入。配套的回放插件需要单独安装:
npm install @rrweb/rrweb-plugin-sequential-id-replay基本用法:在 record 配置中挂载插件
在录制端,通过record的plugins配置项将插件注入事件处理管线:
import { record } from '@rrweb/record'; import { getRecordSequentialIdPlugin } from '@rrweb/rrweb-plugin-sequential-id-record'; record({ emit: function emit(event) { // 将事件发送到服务端 }, plugins: [ getRecordSequentialIdPlugin({ key: '_sid', // 默认值 }), ], });要点说明:
record的plugins选项在 guide.md 中有官方定义(默认值为[],用于“load plugins to provide extended record functions”);getRecordSequentialIdPlugin是工厂函数,调用后返回一个RecordPlugin实例;- 示例中的
key参数可以省略,因为'_sid'就是它的默认值。
生成的插件名与事件形态
插件内部声明了固定的插件名常量PLUGIN_NAME = 'rrweb/sequential-id@1',见 src/index.ts。插件本身不产生EventType.Plugin类型的独立事件,而是通过eventProcessor对每一个即将 emit 的事件原地改写:向事件对象上写入{ [_options.key]: ++id },id 从 1 开始、每次自增。因此一个典型事件的最终形态类似于:
{ type: 3, // IncrementalSnapshot timestamp: 1690000000000, data: { /* ...原始增量数据... */ }, _sid: 42, // 插件写入的顺序 ID }由于eventProcessor对所有类型的事件(FullSnapshot、Meta、IncrementalSnapshot、Custom 等)统一生效,因此整条事件流中的每个事件都能拿到唯一的顺序编号。
源码级原理:eventProcessor 注入链
要理解该插件为什么能“给所有事件加 ID”,需要看 rrweb 录制端的事件处理管线。record/index.ts 中定义了内部eventProcessor:
const eventProcessor = (e: eventWithTime): T => { for (const plugin of plugins || []) { if (plugin.eventProcessor) { e = plugin.eventProcessor(e); } } // ...packFn 等后续处理 return e; };所有事件在 emit 之前都会依次经过每个插件注册的eventProcessor(RecordPlugin接口定义在 packages/types/src/index.ts 的RecordPlugin类型中)。顺序 ID 插件正是利用这一点,在eventProcessor回调里执行Object.assign(event, { [_options.key]: ++id }),实现零侵入地为事件流注入连续编号。
值得注意的实现细节:
- 工厂函数内部用
Object.assign({}, defaultOptions, options)合并默认值,因此传入{ key: 'myId' }时只会覆盖key,其它默认行为不受影响; - 计数器
id是工厂函数闭包内的局部变量,随插件实例创建而复位为 0——这意味着每次调用record()开启新的录制会话时,顺序 ID 都会从 1 重新开始,同一会话内才保证单调递增; - 插件名
'rrweb/sequential-id@1'中的版本号后缀(@1)遵循 rrweb 插件命名约定,便于未来以带版本的方式兼容演进。
回放端配套校验:顺序一致性的守门员
录制端负责“打 ID”,回放端则负责“查 ID”。配套插件@rrweb/rrweb-plugin-sequential-id-replay的使用方式如下(其完整 README 见 packages/plugins/rrweb-plugin-sequential-id-replay/README.md):
import { Replayer } from '@rrweb/replay'; import { getReplaySequentialIdPlugin } from '@rrweb/rrweb-plugin-sequential-id-replay'; const replayer = new Replayer(events, { plugins: [ getReplaySequentialIdPlugin({ // 必须与录制端保持一致 key: '_sid', // 默认值 warnOnMissingId: true, // 默认值 }), ], }); replayer.play(); // ERROR: [sequential-id-plugin]: expect to get an id with value "42", but got "666"回放端插件的行为逻辑(见 rrweb-plugin-sequential-id-replay/src/index.ts):
- 维护一个内部计数器
currentId,初始值为 1; - 对每个事件,先检查
key是否存在于事件上:- 存在:比较事件携带的 ID 与期望值
currentId。相等则currentId++;不相等则输出console.error,错误格式为[sequential-id-plugin]: expect to get an id with value "<期望值>", but got "<实际值>"——这正是官方示例中replayer.play()后出现的报错来源; - 不存在:若
warnOnMissingId为true(默认值),输出console.warn:[sequential-id-plugin]: failed to get id in key: "<key>"。
- 存在:比较事件携带的 ID 与期望值
回放端插件是通过ReplayPlugin的handler挂载到事件回放流程中的,handler的调用点位于 replay/index.ts 中CAST_EVENT状态机投递事件之前。也就是说,校验发生在事件被真正应用到 DOM 之前,一旦 ID 序列断裂,能第一时间在控制台暴露问题。
配置参数一览
| 参数 | 默认值 | 插件端 | 说明 |
|---|---|---|---|
key | '_sid' | 录制端 + 回放端 | 事件上存放顺序 ID 的字段名,两端必须一致 |
warnOnMissingId | true | 仅回放端 | 事件上找不到key字段时是否输出警告 |
关于默认值的补充说明:
- 录制端默认
key为'_sid'(见 record 插件源码 中defaultOptions); - 回放端默认
key同样为'_sid'(见 replay 插件源码 中defaultOptions)。在配置时,强烈建议显式指定与录制端完全相同的key值,避免因文档示例与默认值不一致造成两端错位(例如录制端写入了_sid,回放端却在读_id,结果每个事件都触发failed to get id in key的警告)。
典型应用场景
从插件的能力边界出发,它适合以下场景:
- 事件与业务日志的精确关联:当事件经由服务端存储、再按需拉取回放时,可借助顺序 ID 把回放中的每一个事件与后端日志、错误堆栈、埋点数据一一对上号,定位“回放到第几步出问题”;
- 回放完整性与丢帧检测:事件在传输、压缩或存储过程中若发生缺失/乱序(例如 WebSocket 断线重连、事件分批落库后再合并),回放端插件的连续性校验会立即报错,帮助你发现数据管道的问题;
- 调试录制链路:在开发自定义插件或修改事件流时,顺序 ID 提供了一种低成本的事件计数手段,可以快速确认每个事件是否都经过了预期的处理管线。
需要说明的是,该插件只负责“编号 + 校验”,不参与事件的时间轴调度——回放推进仍由timestamp驱动,顺序 ID 更多承担的是调试与一致性保障职责。若需深入了解 rrweb 事件模型与插件开发,可继续阅读 事件机制文档、插件 API 文档 以及仓库根目录的 guide.md。
【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrweb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考