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 中有了更完善的定义,如果你需要特定类型,它们可能从新的包中导出(例如 PlayerMachineStateSpeedMachineState 现在从 @rrweb/replay 导出)。请查看 package.jsonmainexports 字段了解可用文件。

  • #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:documentNodedocumentTypeNodelegacyAttributestextNodecdataNodecommentNodeelementNodeserializedNodeserializedNodeWithIdserializedElementNodeWithIdserializedTextNodeWithIdIMirrorINodemediaAttributesattributesDataURLOptions

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

次要变更

  • #1432 123a81e 感谢 @Juice10! - Video 和 Audio 元素现在还会捕获 playbackRatemutedloopvolume

  • #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:documentNodedocumentTypeNodelegacyAttributestextNodecdataNodecommentNodeelementNodeserializedNodeserializedNodeWithIdserializedElementNodeWithIdserializedTextNodeWithIdIMirrorINodemediaAttributesattributesDataURLOptions

补丁变更

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 中有了更完善的定义,如果你需要特定类型,它们可能从新的包中导出(例如 PlayerMachineStateSpeedMachineState 现在从 @rrweb/replay 导出)。请查看 package.jsonmainexports 字段了解可用文件。

补丁变更

  • #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 元素现在还会捕获 playbackRatemutedloopvolume

补丁变更

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

补丁变更