@rrweb/record 记录包全解:从 2.0 重大变更到 2.1 性能优化的演进指南
rrweb/record 记录包全解从 2.0 重大变更到 2.1 性能优化的演进指南【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrwebrrweb/record是 rrweb 生态中专用于录制端的独立 npm 包面向需要在浏览器中采集页面事件的前端应用。本文以该包的 CHANGELOG.md 为主线结合包内源码与测试逐版本解读从 2.0.0 到 2.1.5 的关键变更——包括破坏性的产物命名与 UMD 全局名调整、打包体积治理、录制性能优化等并给出可直接落地的安装、引入与迁移方案。读完本文你将掌握rrweb/record的包结构与发布节奏理解每次升级对既有接入代码的实际影响并能写出与 2.x 版本兼容的录制接入代码。一、包定位录制逻辑的唯一出口rrweb/record在 rrweb 生态中的职责非常清晰只暴露录制能力。它的核心实现其实是一个极简包装层// packages/record/src/index.ts import { record } from rrweb; export { record };从 src/index.ts 可以看到包本身只是把主rrweb包中的record函数重新导出re-export。在 packages/record/README.md 中作者也明确说明Currently this package is really just a wrapper around therecordfunction in the mainrrwebpackage. Allrecordrelated code will get moved here in the future.当前该包只是主包record函数的包装未来所有录制相关代码会迁移到这里。因此rrweb/record承担的是一个面向未来的包边界对使用方来说它提供了稳定的录制 API 入口对项目来说它把录制代码与回放代码在包级别彻底隔离为后续 tree-shaking摇树优化与按需加载奠定基础。record函数的真实实现在主包中位于 packages/rrweb/src/record/index.ts其签名结构为function recordT eventWithTime( options: recordOptionsT {}, ): listenerHandler | undefined { const { emit, checkoutEveryNms, // ... 其余录制选项 } options; // ... return stopHandler; // 返回用于停止录制的函数 }它接收可选的recordOptionsT配置对象返回一个停止录制的监听处理器listenerHandler并且record.mirror mirror挂载了内部节点镜像。完整的recordOptions说明可参见仓库根目录的 guide.md 中的record-options一节。二、安装与三种引入方式根据 package.jsonrrweb/record当前版本为2.1.5声明了如下依赖{ dependencies: { rrweb/types: ^2.1.5, rrweb: ^2.1.5, rrweb/utils: ^2.1.5 } }包的类型声明位于dist/index.d.ts浏览器兼容目标为supports es6-class支持 ES6 class 的现代浏览器。方式一通过 npm / bundler 引入推荐npm install rrweb/recordimport { record } from rrweb/record; record({ emit(event) { // 将事件发送到服务端 }, });这是 README.md 推荐的接入方式构建产物兼容现代浏览器、Node.js 以及支持 ES Modules 的打包器。方式二浏览器直接加载ESM不使用打包器时可以直接在浏览器中以 ES Module 方式加载 CDN 资源script typemodule import { record } from https://cdn.rrweb.com/record/current/dist/record.js; /script其中current指向最新稳定版生产环境建议锁定具体版本以保证不可变 URL例如script typemodule import { record } from https://cdn.rrweb.com/record/2.0.0/dist/record.js; /script方式三传统script直接引入UMD 兜底仅用于不支持 ES Module 的旧环境script srchttps://cdn.rrweb.com/record/current/dist/record.umd.cjs/script注意此方式暴露的全局变量名为rrwebRecord而非旧版的rrweb这正是 2.0.0 版本的一项破坏性变更详见下文。三、2.0.0 重大变更升级前必须了解的三件事2.0.0 是该包历史上最大的一次重构对应 CHANGELOG.md 中的2.0.0一节涉及三个破坏性变更与一批功能性补丁。如果你正在从 1.x 升级以下内容直接决定你的代码是否需要改动。3.1 UMD 全局名从rrweb改为rrwebRecord为避免录制器与回放器同时加载在同一页面时发生全局命名冲突2.0.0 将 UMD 全局名拆分录制器recorder全局名rrwebRecord回放器replayer全局名rrwebReplay这意味着所有通过script标签直接引用 UMD 产物的老代码都需要把全局变量的引用从rrweb改为rrwebRecord。3.2 分发产物文件名、路径与扩展名全面调整2.0.0 重做了构建产物规范对应 PR #1497核心变化如下所有.js文件现在都是ES Modules可用于现代浏览器、Node.js 以及支持 ESM 的打包器所有 npm 包同时附带.cjs与.umd.cjs文件.umd.cjsCommonJS 格式且内联打包所有依赖便于在浏览器环境用一个文件直接引入类似旧版.js文件.cjsCommonJS 格式用于较老的 Node.js 环境新增/umd/输出目录与/dist/并存从而可以以.js扩展名提供 UMD 文件而不破坏 package.json 中/dist/下所有.js均为模块的约定类型导出更规范如果需要特定类型例如PlayerMachineState、SpeedMachineState它们现在从rrweb/replay等新包导出具体可用文件以各包package.json的main与exports字段为准。从当前 package.json 可以直观看到这套新规范{ type: module, main: ./dist/record.cjs, module: ./dist/record.js, unpkg: ./dist/record.umd.cjs, jsdelivr: ./umd/record.js, typings: dist/index.d.ts, exports: { .: { import: { types: ./dist/index.d.ts, default: ./dist/record.js }, require: { types: ./dist/index.d.cts, default: ./dist/record.cjs } } }, files: [umd, dist, package.json] }迁移建议如果你的代码通过import rrweb from rrweb方式使用则本次变更对你几乎无感但如果你直接引用了分发文件例如rrweb/typings/...、rrdom/es或在script标签中直接引入旧版rrweb-all.js、rrweb-record.js、rrweb-replay.js则必须更新路径——改为引用.umd.cjs文件或改用新包。3.3 移除rrweb-all.js/rrweb-record.js/rrweb-replay.js这三个文件从rrweb主包中彻底移除取而代之的是按职责拆分的独立包rrweb/all聚合导出录制 回放 打包器rrweb/record仅录制rrweb/replay仅回放从 packages/all/src/index.ts 可以看到rrweb/all的聚合方式export * from rrweb; export * from rrweb/packer; import rrweb/dist/style.css;它重新导出主包全部 API 与打包器并附带引入回放所需的样式文件。如果你以前用rrweb-all.js一把梭现在应当按需拆分引入只加载自己需要的部分。3.4 2.0.0 的功能性补丁除破坏性变更外2.0.0 还包含一系列稳定性与兼容性修复变更点说明移除各 bundle 中 base64 内联的 worker 源码减小产物体积worker 改为独立文件加载支持已废弃的addRule/removeRule方法兼容仍在使用旧 CSSOM API 的页面PR #1515捕获WebGLRenderingContext前先校验其是否存在避免在不支持 WebGL 的环境抛错PR #1777patch函数迁移至rrweb/utils提升打包复用性减少重复代码PR #1631正确识别 Angular 包装后的 MutationObserver修复 Angular 框架下录制失效的问题PR #1597从rrweb/recordbundle 中摇树掉回放专用的postcss代码录制包不再携带回放才需要的 CSS 处理逻辑PR #1837新增/umd/输出目录见 3.2 节说明四、打包体积治理一条有测试约束的硬红线rrweb/record的体积不是靠自觉维护的而是被自动化测试强制约束。在 packages/record/test/record.test.ts 中可以看到两个关键断言// 修复前 ESM bundle 大小397373 字节 // 修复后 ESM bundle 大小161287 字节 // 修复后的 ESM bundle 必须比基线至少小 200 KiB const BASELINE_RECORD_JS_BYTES 397373; const MAX_RECORD_JS_BYTES BASELINE_RECORD_JS_BYTES - 200 * 1024;测试逻辑分三层导出可用性typeof record function保证 API 形态稳定无回放代码泄漏遍历dist/下所有.js/.cjs产物断言内容中不包含postcss字样——这就是 3.4 节摇树掉回放专用 postcss的回归防线防止未来重构又把回放依赖带进录制包体积上限dist/record.js的大小必须小于等于397373 - 200 * 1024 ≈ 192765字节。实测摇树修复后为 161287 字节比 2.0.0 基线瘦身约 236 KB近 60%。这一设计思路值得借鉴把体积当作与功能正确性同等重要的非功能需求用单测持续守护。也正因为此rrweb/record才能以极小的包体承载完整录制能力。五、2.1.x 增量演进性能与健壮性打磨进入 2.1 系列后rrweb/record没有再做破坏性变更而是聚焦性能与细节。逐版本梳理如下2.1.5录制热路径性能优化这是 2.1 系列最重要的一次性能更新包含两点未受污染的 DOM 访问器性能提升自 #1509 起为绕开某些库对parentNode等访问器的篡改代码改为使用dom.parentNode(el)这类封装调用。2.1.5 进一步优化避免每次调用时分配字符串——这些调用位于所有录制热路径上字符串分配开销会被放大到每次 DOM 变更录制期 mutation 处理效率提升重排了 mutation 处理顺序录制效率显著改善同时新的 mutation 排序还带来更快的回放性能。该问题此前被多位社区成员反复报告是录制侧公认的痛点。对应地packages/rrweb/src/record/下的 mutation.ts 与 observer.ts 就是这些优化的落点所在——DOM 变更观察与序列化在每次用户交互时都会被触发属于典型的热路径。2.1.0绝对 URL 转相对 URL 的 hash 修复修复了一个边界 bug当 URL 中包含 hash#...时绝对 URL 转相对 URL 的转换逻辑会产生错误结果。这影响的是录制事件中资源 URL 的归一化处理修复后带 hash 的链接也能被正确转为相对地址。2.1.1 / 2.1.2 / 2.1.3 / 2.1.4纯依赖同步这几个版本没有rrweb/record自身的代码变更只是随主包与类型包一起同步版本rrweb、rrweb/types、rrweb/utils同版本对齐。这正是 rrweb monorepo 采用的changesets 统一版本管理策略所有包保持相同版本号通过turbo工作流协调构建与发布。2.0.1补丁同步同样为依赖同步版本未包含本包独立变更。六、版本发布节奏与全版本一览rrweb/record的发布遵循 changesets 规范所有相关包rrweb、rrweb/types、rrweb/utils保持版本同步。从 CHANGELOG.md 整理的完整版本时间线如下版本类型核心内容2.1.5Patch未污染 DOM 访问器性能优化mutation 处理效率提升2.1.4Patch依赖同步2.1.3Patch依赖同步2.1.2Patch依赖同步2.1.1Patch依赖同步2.1.0Patch修复含 hash 的绝对 URL 转相对 URL2.0.1Patch依赖同步2.0.0MajorUMD 全局名改名产物路径/命名/扩展名重构移除rrweb-*.js独立文件若干兼容性补丁2.0.0-alpha.15 ~ 2.0.0-alpha.20Major/Alpha2.0.0 的预发布迭代含addRule/removeRule支持、patch函数迁移等需要注意的是2.0.0-alpha.x 系列属于预发布版本其中出现的变更如db20184保持包版本与其他包同步最终都汇总进了 2.0.0 正式版。七、包内工程配置速查如果你要本地开发或调试rrweb/recordpackage.json 中几个常用脚本值得关注{ scripts: { dev: vite build --watch, build: yarn turbo run prepublish, test: yarn build vitest run, test:watch: vitest watch, check-types: tsc -noEmit, prepublish: tsc -noEmit vite build, lint: yarn eslint src/**/*.ts } }yarn workspace rrweb/record build通过 turbo 触发prepublish先做类型检查再走 vite 构建体积测试要求先执行此步否则 record.test.ts 会因缺少dist/record.js而报错yarn workspace rrweb/record test构建后运行 vitest即上文所述的三项体积/内容断言构建工具链vite vite-plugin-dts生成.d.ts类型、vitest单测、puppeteer浏览器相关测试。八、迁移检查清单综合以上分析从旧版本升级到rrweb/record2.x 时建议逐项核对全局变量引用UMD 方式使用的全局名是否已从rrweb改为rrwebRecord脚本标签路径直接引入的rrweb-record.js等文件路径是否已替换为.umd.cjs或新包 CDN 地址产物导入若通过import使用确认打包器正确解析exports字段import走dist/record.jsrequire走dist/record.cjs类型引用需要回放侧状态机类型如PlayerMachineState时改从rrweb/replay导入浏览器兼容包目标环境为supports es6-class不支持 ES6 class 的老浏览器需自行引入 polyfill 或使用 UMD 产物体积预期ESM 产物约 161 KB摇树修复后若接入方同时打包主包可进一步通过 tree-shaking 获益——录制场景应优先选择rrweb/record而非rrweb/all以规避回放专用代码如 postcss被带入产物。结语rrweb/record虽然当前仍以薄包装形态存在但它的出现标志着 rrweb 在包边界、构建规范与体积治理上的系统性演进2.0.0 用一套破坏性变更换来了清晰的模块划分与现代化的产物矩阵2.1.x 则把优化火力集中在录制热路径的性能上并用自动化测试锁住录制包绝不携带回放代码的底线。对于接入方而言理解 CHANGELOG.md 中的每一次版本变化就是理解录制端 API 稳定性与性能边界的最佳入口——从 2.1.x 开始你可以放心地把record作为长期稳定的录制入口来依赖。【免费下载链接】rrwebrecord and replay the web项目地址: https://gitcode.com/gh_mirrors/rr/rrweb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考