Skip to content

rrweb-snapshot ​

概述 ​

将 DOM 快照为带有状态且可序列化的数据结构, 并提供通过快照重建 DOM 的能力。

API ​

本模块导出以下方法:

snapshot ​

snapshot 会遍历 DOM,并返回一个带有状态且可序列化的数据结构,用于表示当前 DOM 的视图。

快照过程中会完成以下几件事:

  1. 将部分 DOM 状态内联到 HTML 属性中,例如 HTMLInputElement 的 value。
  2. 将 script 标签转换为 noscript 标签,以避免脚本被执行。
  3. 尝试内联样式表,确保本地样式表可以被使用。
  4. 将 href、src 和 CSS 中的相对路径转换为绝对路径。
  5. 为每个节点分配一个 id,并在快照完成时返回 id 与节点的映射表。

rebuild ​

rebuild 会根据已拍摄的快照构建 DOM。

在浏览器环境中,rebuild() 是一个底层 API,除非传入 UNSAFE_allowUnprotectedRebuild: true,否则它要求使用由 rebuildIntoSandboxedIframe() 创建的 document。不可信的回放数据不得直接重建到顶层 document 或调用方自行创建的 iframe document 中。

在浏览器中使用时,优先选择 rebuildIntoSandboxedIframe:

rebuildIntoSandboxedIframe 要求显式传入 root 元素。

ts
const { iframe, node } = rebuildIntoSandboxedIframe(snapshot, {
  root: document.body,
  cache,
  mirror,
});

如果需要单独管理 iframe,请在调用 rebuild() 之前使用 createSandboxedIframe() 创建它。

如果你明确接受脚本执行风险,可以向 rebuild 传入 UNSAFE_allowUnprotectedRebuild: true。

重建过程中会完成以下几件事:

  1. 如果节点是 Element,则添加 data-rrid 属性。
  2. 创建一些额外的 DOM 节点(如文本节点),用于放置内联 CSS 和部分状态。
  3. 如果节点包含额外的子 DOM,则添加 data-extra-child-index 属性。

serializeNodeWithId ​

serializeNodeWithId 可以将节点序列化为带 id 的快照格式。

buildNodeWithSN ​

buildNodeWithSN 会根据序列化节点构建 DOM,并将序列化信息存储在 mirror.getMeta(node) 中。

在 GitHub 上编辑 README

rrweb-snapshot 发布说明 ​

2.1.1 ​

本版本无变更,仅为与其他包保持版本同步而提升版本号

2.1.0 ​

补丁变更 ​

2.0.1 ​

补丁变更 ​

  • #1854 5f52d63 感谢 @eoghanmurray! - 修复网页被第三方库猴子补丁(monkey patch)修改后,Webkit/Safari 中 MutationObserver 失效的问题

2.0.0 ​

重大变更 ​

  • #1497 2606a2a 感谢 @Juice10! - 分发文件采用了新的文件名、路径和扩展名。重要提示:如果你直接引用分发文件或类型,可能需要更新你的路径/文件名,例如你从 rrweb/typings/... 或 rrdom/es 导入。但如果你是通过 import rrweb from 'rrweb' 使用,则不会察觉到此变更带来的差异。 如果你直接在 script 标签中引入 rrweb 文件,可能需要将路径更新为对应的 .umd.cjs 文件。所有 .js 文件现在都使用 ES 模块,可在现代浏览器、node.js 以及支持 ES 模块的打包器中使用。所有 npm 包现在还同时提供 .cjs 和 .umd.cjs 文件。.umd.cjs 文件是将所有文件打包在一起的 CommonJS 模块,便于向浏览器环境分发单个文件(类似于之前的 .js 文件)。.cjs 文件是可在旧版 Node.js 环境中使用的 CommonJS 模块。类型在 package.json 中有了更完善的定义,如果你需要特定类型,它们可能从新的包中导出(例如 PlayerMachineState 和 SpeedMachineState 现在从 @rrweb/replay 导出)。请查看 package.json 的 main 和 exports 字段了解可用文件。

  • #1834 43e4f5b 感谢 @Juice10! - 默认要求浏览器中的 rebuild() 调用必须以 rebuildIntoSandboxedIframe() 或 createSandboxedIframe() 创建的 document 为目标。对于不可信的回放数据请使用这些辅助函数;仅在明确接受脚本执行风险时才传入 UNSAFE_allowUnprotectedRebuild: true。

    rrweb 现在将 UNSAFE_replayCanvas 重建标记为显式的不安全路径,因为 canvas 回放会向回放 iframe 添加脚本权限。

  • #1593 5a78938 感谢 @daibhin! - NodeType 枚举已从 rrweb-snapshot 移至 @rrweb/types 以下类型已从 rrweb-snapshot 移至 @rrweb/types:documentNode、documentTypeNode、legacyAttributes、textNode、cdataNode、commentNode、elementNode、serializedNode、serializedNodeWithId、serializedElementNodeWithId、serializedTextNodeWithId、IMirror、INode、mediaAttributes、attributes 和 DataURLOptions

  • #868 e4f680e 感谢 @Juice10! - 移除 INode / node.__sn 的用法,改用 Mirror 作为唯一事实来源。

次要变更 ​

  • #1432 123a81e 感谢 @Juice10! - Video 和 Audio 元素现在还会捕获 playbackRate、muted、loop、volume。

  • #1503 335639a 感谢 @Juice10! - 录制 dialog 的模态状态,以便在 rrweb 中回放。(目前 rrweb-snapshot 的 rebuild 不支持触发 dialog.showModal())

  • #1188 bc84246 感谢 @benjackwhite! - feat:扩展 maskInputFn,将 HTMLElement 传递给决策函数

  • #1170 d2582e9 感谢 @mydea! - feat:确保切换输入框类型时密码输入保持脱敏状态

  • #1152 eac9b18 感谢 @mydea! - feat:忽略 video/audio 元素上的 autoplay 属性

  • #1310 7c0dc9d 感谢 @benjackwhite! - 扩展 maskTextFn,将 HTMLElement 传递给决策函数

  • #1035 2a80949 感谢 @Juice10! - 新增对跨域 iframe 录制的支持,包括事件/id 重映射以及 genId 导出支持。

  • #989 3809060 感谢 @YunFeng0817! - 新增对可构造样式表 adoptedStyleSheets 的录制与回放支持,包括样式表变更、replace/replaceSync、shadow root、iframe、实时模式以及虚拟 DOM 回放。

  • #895 de755ae 感谢 @Juice10! - 为回放新增快进虚拟 DOM 优化。

补丁变更 ​

  • #1580 47a7c3f 感谢 @guntherjh! - 处理调用 adaptCssForReplay 时 postcss 抛出的异常

  • #1386 a2c8a1a 感谢 @ababik! - 修复可选的 maskInputFn 在创建全量快照时被意外忽略的问题

  • #1417 40bbc25 感谢 @YunFeng0817! - fix:修复 style 元素 textContent 重复导致增量样式变更失效的问题

  • #1762 22bc4c3 感谢 @Juice10! - 从所有构建产物中移除 base64 内联的 worker 源码

  • #1279 11f6567 感谢 @eoghanmurray! - 扩展 fixBrowserCompatibilityIssuesInCSS,使其也处理内联样式表

  • #1615 dc20cd4 感谢 @eoghanmurray! - 提升 splitCssText 处理包含大量 CSS 内容的 <style> 元素时的性能——参见 #1603

  • #1640 3e9e42f 感谢 @eoghanmurray! - 提升 splitCssText 处理包含大量 CSS 内容的 <style> 元素时的性能——参见 #1603

  • #1464 03b5216 感谢 @colingm! - 更好地支持与修改内置 Array.from 函数的旧库(如 MooTools 和 Prototype.js)共存

  • #1481 46f1b25 感谢 @eoghanmurray! - 针对影响复杂 tailwind css 回放的 bug #1457 添加修复和测试

  • #1476 cbbd1e5 感谢 @eoghanmurray! - 修复多处 background-clip 替换的问题

  • #1600 a6893f7 感谢 @eoghanmurray! - #1575 修复 postcss 在处理被任意拆分的 CSS 内容时可能崩溃的问题

  • #1133 c28ef5f 感谢 @eoghanmurray! - 修复:CSS transition 在 Firefox 中重建时被错误应用的问题。推测原因是 Firefox 未能及时完成样式解析,从而对 CSS 中设置了非零 margin 且带有 transition 的元素应用了默认的 margin:0。

    Firefox 相关 bug 报告:https://bugzilla.mozilla.org/show_bug.cgi?id=1816672

  • #1387 5e7943d 感谢 @H4ad! - 避免每次都重新创建相同的元素,改为缓存该元素并仅对其进行更新。

    优化前:779k ops/s 优化后:860k ops/s

    基准测试:https://jsbench.me/ktlqztuf95/1

  • #1468 4014305 感谢 @eoghanmurray! - inlineImages:快照期间避免为同源图片的内联添加事件监听器(异步监听器会修改快照,可能导致问题)

  • #1287 efdc167 感谢 @Juice10! - 将所有项目升级到 typescript 4.9.5

  • #1130 f6f07e9 感谢 @AgentWrapper! - 修复:内联样式表时,让样式表 URL 的相对路径检测覆盖更多类型的 URL 协议。

  • #1095 1385f7a 感谢 @YunFeng0817! - 修复 shadow DOM 重复的问题

  • #1183 d7c72bf 感谢 @mydea! - fix:确保检查时将属性名转为小写

  • #1705 f2419f2 感谢 @megboehlert! - 使用 ownerNode.baseURI 来序列化样式表的 href

  • #1440 c0f83af 感谢 @daibhin! - 改进嵌套 CSS 选择器的拆分,正确处理引号文本中出现逗号或括号的情况

  • #1467 e96f668 感谢 @eoghanmurray! - #1434 性能优化后的 bug 修复:修复 blob URL 残留在共享的 anchor 元素上且之后无法修改的问题

  • #1272 58c9104 感谢 @eoghanmurray! - 性能:遍历样式规则时避免创建中间数组

  • #1126 227d43a 感谢 @YunFeng0817! - 将所有 CommonJS 模块打包脚本的后缀从 'js' 重构为 cjs #1087。

  • #1493 82f6fec 感谢 @eoghanmurray! - 回放:替换 CSS 解析器正则表达式中的负向回顾断言(negative lookbehind),因为它会在 Safari 16 中引发问题

  • #1331 02cc62d 感谢 @billyvg! - 修复被屏蔽元素的尺寸未生效的问题

  • #1148 d0fdc0f 感谢 @YunFeng0817! - 改进:为 snapshot.ts 的文本脱敏函数添加 try catch。修复 #1118。

  • #1482 f3cf092 感谢 @AlfieJones! -(当 recordCanvas: true 时):确保使用 doc.createElement 而非 document.createElement,以便在 jsdom 等非浏览器环境中使用

  • #1351 a2be77b 感谢 @eoghanmurray! - 当 <textarea> 已预填内容时,避免重复录制其值 #1301

  • #1837 527d9d3 感谢 @Juice10! - 从 @rrweb/record 构建产物中 tree-shake 掉仅用于回放的 postcss 代码。

  • #1401 f7c6973 感谢 @dengelke! - 修复 CSS 解析错误

  • #1287 efdc167 感谢 @Juice10! - 为 Chrome/Edge 的 CSS @import 转义 bug 添加临时解决方案:https://bugs.chromium.org/p/chromium/issues/detail?id=1472259

  • #1431 a7c33f2 感谢 @eoghanmurray! - 确保 :hover 在回放器中生效,即使规则位于媒体查询之内 遵循 max-device-width 和 min-device-width 媒体查询的意图,使其效果在回放器环境中得以体现

  • #1614 6f4e691 感谢 @billyvg! - 改为忽略所有 link[rel="modulepreload"],而不仅是带有 as="script" 的项

  • #1535 04ee6ed 感谢 @eoghanmurray! - 对 #1458 之后 :hover 的替换方式做小幅简化

  • #1437 5fbb904 感谢 @eoghanmurray! - 边界情况:支持对(罕见地)包含多个文本节点的 <style> 元素进行变更处理

  • #1533 d350da8 感谢 @jeffdnguyen! - 修复嵌套样式表的 url() 重写问题,改为在字符串化过程中重写,而非在之后重写

  • #1512 d08624c 感谢 @eoghanmurray! - 优化:跳过叶子元素的脱敏检查

  • #1174 e7f0c80 感谢 @wfk007! - 修复:#1172 不要替换图片原有的 onload 函数

  • #1155 8aea5b0 感谢 @YunFeng0817! - Feat:为序列化元素添加 'isCustom' 标记。

    该标记用于表示元素是否为自定义元素,有助于回放自定义元素的 :defined 伪类。

  • #1374 314a8dd 感谢 @andrewpomeroy! - 捕获标记为 rel="preload" 的样式表

  • #1731 76df979 感谢 @eoghanmurray! - 修复 #1705 之后缺失的导入

  • #1157 8e47ca1 感谢 @mydea! - fix:显式处理 null 属性值

  • #1349 07ac5c9 感谢 @eoghanmurray! - 文本脱敏时的快照性能:避免在递归遍历 DOM 时重复调用 closest

  • #1253 c6600e7 感谢 @mydea! - 修复 Safari 中捕获的 CSS 规则

  • #1704 33e01f5 感谢 @eoghanmurray! - 在 /dist/ 之外提供 /umd/ 输出目录,以便提供带 .js 扩展名的 UMD(Universal Module Definition)文件,同时不违背 package.json 中 /dist/ 下所有 .js 文件均为模块的约定

  • #760 e08706a 感谢 @eoghanmurray! - 新增 slimDOM 选项以屏蔽 <title> 标签上的动画;当 slimDOM 使用 'all' 值时启用

  • #1509 be6bf52 感谢 @Juice10! - 对内置方法进行反向猴子补丁,以支持 LWC(以及其他会对内置方法打猴子补丁的框架,如 angular)。

  • #1047 9bbc3e0 感谢 @Juice10! - 序列化 CSS 规则时保留 -webkit-background-clip: text。

  • #1012 6f44bb7 感谢 @Juice10! - 确保回放插件的 onBuild 钩子对新追加的变更节点和顶层重建的 document 节点都会运行。

  • #995 55ebce7 感谢 @YunFeng0817! - 修复延迟内联样式表链接的回放:改为更新现有 link/style 节点的属性,而不是添加子节点。

  • #970 23e3a73 感谢 @Juice10! - 在普通属性之后应用内部 rr_* 属性,使 rr_dataURL 等仅用于回放的值不会被序列化的 DOM 属性覆盖。

  • #927 fd85c79 感谢 @Juice10! - 通过正确处理负数和未序列化的节点 id,修复 iframe 重新加载和 rrdom diff 问题。

  • #984 6eaec04 感谢 @QuentinLowe! - 修复第二次全量快照之后 iframe 回放失败的问题。

  • #994 a9a2559 感谢 @wfk007! - 通过在 mirror 中跟踪被忽略的节点,修复使用 slimDOMOptions 时丢失变更的问题。

  • #938 f3064c1 感谢 @lele0108! - 修复 SVG <use href="#..."> 的快照序列化,使本地片段引用被保留,而不是被转换为绝对 URL。

  • #942 f03504a 感谢 @YunFeng0817! - 修复对由 ShadyDOM 和 @lwc/synthetic-shadow 提供 polyfill 的 Shadow DOM 的录制与回放。

  • #944 f1b23dd 感谢 @YunFeng0817! - 修复快进回放,使通过虚拟 DOM 路径重建时 iframe 内的 canvas 图像数据能够被恢复。

  • #906 9da1e43 感谢 @Juice10! - 修复快照序列化中的 issue #904。

  • #903 058c457 感谢 @Juice10! - 加快大量新增 DOM 节点的快照速度。

  • #909 d5d877e 感谢 @Juice10! - 在样式表加载时进行内联,以捕获加载较晚的样式表内容。

2.0.0-alpha.19 ​

补丁变更 ​

2.0.0-alpha.18 ​

重大变更 ​

  • #1593 5a78938 感谢 @daibhin! - NodeType 枚举已从 rrweb-snapshot 移至 @rrweb/types 以下类型已从 rrweb-snapshot 移至 @rrweb/types:documentNode、documentTypeNode、legacyAttributes、textNode、cdataNode、commentNode、elementNode、serializedNode、serializedNodeWithId、serializedElementNodeWithId、serializedTextNodeWithId、IMirror、INode、mediaAttributes、attributes 和 DataURLOptions

补丁变更 ​

2.0.0-alpha.17 ​

次要变更 ​

  • #1503 335639a 感谢 @Juice10! - 录制 dialog 的模态状态,以便在 rrweb 中回放。(目前 rrweb-snapshot 的 rebuild 不支持触发 dialog.showModal())

补丁变更 ​

  • #1417 40bbc25 感谢 @YunFeng0817! - fix:修复 style 元素 textContent 重复导致增量样式变更失效的问题

  • #1533 d350da8 感谢 @jeffdnguyen! - 修复嵌套样式表的 url() 重写问题,改为在字符串化过程中重写,而非在之后重写

  • #1509 be6bf52 感谢 @Juice10! - 对内置方法进行反向猴子补丁,以支持 LWC(以及其他会对内置方法打猴子补丁的框架,如 angular)。

2.0.0-alpha.16 ​

补丁变更 ​

2.0.0-alpha.15 ​

重大变更 ​

  • #1497 2606a2a 感谢 @Juice10! - 分发文件采用了新的文件名、路径和扩展名。重要提示:如果你直接引用分发文件或类型,可能需要更新你的路径/文件名,例如你从 rrweb/typings/... 或 rrdom/es 导入。但如果你是通过 import rrweb from 'rrweb' 使用,则不会察觉到此变更带来的差异。 如果你直接在 script 标签中引入 rrweb 文件,可能需要将路径更新为对应的 .umd.cjs 文件。所有 .js 文件现在都使用 ES 模块,可在现代浏览器、node.js 以及支持 ES 模块的打包器中使用。所有 npm 包现在还同时提供 .cjs 和 .umd.cjs 文件。.umd.cjs 文件是将所有文件打包在一起的 CommonJS 模块,便于向浏览器环境分发单个文件(类似于之前的 .js 文件)。.cjs 文件是可在旧版 Node.js 环境中使用的 CommonJS 模块。类型在 package.json 中有了更完善的定义,如果你需要特定类型,它们可能从新的包中导出(例如 PlayerMachineState 和 SpeedMachineState 现在从 @rrweb/replay 导出)。请查看 package.json 的 main 和 exports 字段了解可用文件。

补丁变更 ​

  • #1468 4014305 感谢 @eoghanmurray! - inlineImages:快照期间避免为同源图片的内联添加事件监听器(异步监听器会修改快照,可能导致问题)

  • #1493 82f6fec 感谢 @eoghanmurray! - 回放:替换 CSS 解析器正则表达式中的负向回顾断言(negative lookbehind),因为它会在 Safari 16 中引发问题

  • #1482 f3cf092 感谢 @AlfieJones! -(当 recordCanvas: true 时):确保使用 doc.createElement 而非 document.createElement,以便在 jsdom 等非浏览器环境中使用

  • #760 e08706a 感谢 @eoghanmurray! - 新增 slimDOM 选项以屏蔽 <title> 标签上的动画;当 slimDOM 使用 'all' 值时启用

2.0.0-alpha.14 ​

补丁变更 ​

  • #1464 03b5216 感谢 @colingm! - 更好地支持与修改内置 Array.from 函数的旧库(如 MooTools 和 Prototype.js)共存

  • #1481 46f1b25 感谢 @eoghanmurray! - 针对影响复杂 tailwind css 回放的 bug #1457 添加修复和测试

  • #1476 cbbd1e5 感谢 @eoghanmurray! - 修复多处 background-clip 替换的问题

  • #1387 5e7943d 感谢 @H4ad! - 避免每次都重新创建相同的元素,改为缓存该元素并仅对其进行更新。

    优化前:779k ops/s 优化后:860k ops/s

    基准测试:https://jsbench.me/ktlqztuf95/1

  • #1440 c0f83af 感谢 @daibhin! - 改进嵌套 CSS 选择器的拆分,正确处理引号文本中出现逗号或括号的情况

  • #1467 e96f668 感谢 @eoghanmurray! - #1434 性能优化后的 bug 修复:修复 blob URL 残留在共享的 anchor 元素上且之后无法修改的问题

2.0.0-alpha.13 ​

次要变更 ​

  • #1432 123a81e 感谢 @Juice10! - Video 和 Audio 元素现在还会捕获 playbackRate、muted、loop、volume。

补丁变更 ​

2.0.0-alpha.12 ​

次要变更 ​

补丁变更 ​

  • #1272 58c9104 感谢 @eoghanmurray! - 性能:遍历样式规则时避免创建中间数组

  • #1351 a2be77b 感谢 @eoghanmurray! - 当 <textarea> 已预填内容时,避免重复录制其值 #1301

  • #1431 a7c33f2 感谢 @eoghanmurray! - 确保 :hover 在回放器中生效,即使规则位于媒体查询之内 遵循 max-device-width 和 min-device-width 媒体查询的意图,使其效果在回放器环境中得以体现

  • #1155 8aea5b0 感谢 @YunFeng0817! - Feat:为序列化元素添加 'isCustom' 标记。

    该标记用于表示元素是否为自定义元素,有助于回放自定义元素的 :defined 伪类。

  • #1374 314a8dd 感谢 @andrewpomeroy! - 捕获标记为 rel="preload" 的样式表

  • #1349 07ac5c9 感谢 @eoghanmurray! - 文本脱敏时的快照性能:避免在递归遍历 DOM 时重复调用 closest

2.0.0-alpha.11 ​

补丁变更 ​

2.0.0-alpha.10 ​

补丁变更 ​

2.0.0-alpha.9 ​

补丁变更 ​

2.0.0-alpha.8 ​

次要变更 ​

补丁变更 ​

2.0.0-alpha.7 ​

次要变更 ​

  • #1170 d2582e9 感谢 @mydea! - feat:确保切换输入框类型时密码输入保持脱敏状态

补丁变更 ​

2.0.0-alpha.6 ​

次要变更 ​

补丁变更 ​

2.0.0-alpha.5 ​

补丁变更 ​