资讯动态

rrweb 录制存储优化实战:DOM 屏蔽、sampling 抽样、压缩与去冗全指南

发布时间:2026/9/21 15:35:54 来源:尧图企业网站定制
前端可观测性开发工具【免费下载链接】rrwebrecord and replay the web项目地址https://gitcode.com/gh_mirrors/rr/rrweb点击查看免费下载rrweb 以录制即事件流的方式工作录制数据量与页面复杂度和用户交互频率成正比在高交互场景下可能远超预期。本文基于官方文档 docs/recipes/optimize-storage.zh_CN.md英文版见 docs/recipes/optimize-storage.md系统梳理四类存储优化策略屏蔽 DOM 元素、sampling 抽样降频、压缩与去冗并结合 packages/rrweb 与 packages/packer 的源码实现讲清每个配置项的真实生效机制与默认行为。读完本文你将能够为你的录制场景组合出一套可落地的存储优化方案。优化策略整体分为三类屏蔽 DOM 元素减少录制的内容范围sampling 配置抽样减少录制的数据量与事件频率去冗与压缩减少数据存储体积。何时需要优化存储识别数据爆炸场景在默认配置下rrweb 会录制全量快照、增量 DOM 变更、鼠标移动/交互、滚动、输入、媒体交互、视口变化等事件流。以下场景最容易产生高于预期的数据量长列表滚动会持续触发大量滚动事件与 DOM 变更复杂的 SVG节点数量大序列化后体积可观包含 JS 控制动画的元素每一帧都可能产生属性变更或子树变更的 mutation 事件canvas 动画逐帧绘制调用或逐帧截图本身就是高数据量来源。这些元素往往不是回放时的关注重点因此第一层优化就是让 rrweb 直接忽略它们。策略一屏蔽 DOM 元素缩小录制范围blockClass / blockSelector整棵子树不入镜在调用record时传入blockClass默认值为rr-block或blockSelector命中该选择器的元素会被视为阻塞元素其整个子树都不会进入录制数据回放时以占位形式呈现。import { record } from rrweb/record; record({ emit(event) {}, blockClass: rr-block, // 默认值页面中带 rr-block class 的子树不录制 blockSelector: .ads, #live-region, // 额外用 CSS 选择器指定要屏蔽的元素 });从源码看屏蔽判断发生在快照snapshot与增量incremental两条链路中。核心实现是 packages/rrweb-snapshot/src/snapshot.ts 中的_isBlockedElement它支持blockClass为字符串用classList.contains判断或正则表达式对每个 className 做test。同时在 packages/rrweb/src/record/observer.ts 中几乎所有事件观察器鼠标交互、滚动、输入、媒体交互等在派发事件前都会调用isBlocked做前置过滤例如initMouseInteractionObserver中对目标元素执行isBlocked(target, blockClass, blockSelector, true)见 observer.ts。因此被屏蔽的元素既不会出现在快照中也不会产生增量事件。ignoreClass / ignoreSelector保留结构、忽略内容与block不同ignore默认 class 为rr-ignore表示元素结构仍然会被录制但元素内部的变化属性、子树变更被忽略。典型用途是聊天消息列表、日志面板等高频刷新区域结构占位保留内容变化不产生事件。需要权衡的副作用屏蔽会带来一个直接后果被屏蔽区域在回放中不可见。如果该区域是产品核心 UI例如价格、图表屏蔽策略会导致回放信息缺失。因此建议只对与业务无关或非关注点的高数据量区域使用并配合下面的抽样与压缩策略分层使用。策略二sampling 抽样从频率维度削减事件当录制内容无法减少时可以通过sampling配置降低各类事件的录制频率甚至完全关闭。SamplingStrategy的完整定义位于 packages/types/src/index.ts下面结合源码逐一说明每个字段的行为与默认值。示例 1整体开关与节流阈值import { record } from rrweb/record; record({ emit(event) {}, sampling: { // 不录制鼠标移动事件 mousemove: false // 不录制鼠标交互事件 mouseInteraction: false, // 设置滚动事件的触发频率 scroll: 150 // 每 150ms 最多触发一次 // set the interval of media interaction event media: 800 // 设置输入事件的录制时机 input: last // 连续输入时只录制最终值 } })各字段的真实生效机制均可在 packages/rrweb/src/record/observer.ts 中找到对应实现字段取值默认行为源码实现mousemovefalse或毫秒数默认节流阈值 50msinitMoveObserverobserver.ts中sampling.mousemove false直接跳过注册为数字时作为位置采集的节流阈值L118-L119mousemoveCallback毫秒数默认 500ms控制位置批量上报回调的节流间隔L120-L123与mousemove分层节流mouseInteractionfalse、true或对象默认录制全部交互initMouseInteractionObserverobserver.ts中 false时跳过注册L200scroll毫秒数默认 100msinitScrollObserver中throttle(..., sampling.scroll \|\| 100)L348media毫秒数默认 500msinitMediaInteractionObserver中throttle(..., sampling.media \|\| 500)L1048inputall|last默认all监听input与changesampling.input last时只监听change事件配合cbWithDedup对重复值去重L466-L484几个容易忽视的细节mousemove: false与mousemoveWait的关系mousemoveWait是旧版参数。在 packages/rrweb/src/record/index.ts 中当mousemoveWait存在而sampling.mousemove未定义时会自动迁移到sampling.mousemove两者等价建议统一使用sampling。input: last的意义连续输入多字符时只记录最终值牺牲逐键回放的精细度换取输入事件数量的大幅下降。如果你的回放需要精确还原输入过程请保留all。阈值型参数的取舍scroll、media等节流阈值越大事件越稀疏回放时滚动/媒体进度会呈现跳跃感建议在数据量与回放平滑度之间取平衡。示例 2细粒度开关鼠标交互类型当页面中某类交互事件量极大例如持续聚焦/失焦触发Focus/Blur可以只关闭特定类型import { record } from rrweb/record; record({ emit(event) {}, sampling: { // 定义不录制的鼠标交互事件类型可以细粒度的开启或关闭对应交互录制 mouseInteraction: { MouseUp: false, MouseDown: false, Click: false, ContextMenu: false, DblClick: false, Focus: false, Blur: false, TouchStart: false, TouchEnd: false, }, }, });这里的键名与 packages/types/src/index.ts 中MouseInteractions枚举一一对应还包括TouchMove_Departed、TouchCancel等。源码中initMouseInteractionObserver会将对象形式的配置转换为disableMap只有disableMap[eventKey] ! true时才注册对应监听器observer.ts从而实现按需开关。其他抽样项canvasSamplingStrategy还包含canvas字段all表示逐条录制所有 canvas 绘制调用设置为 160 之间的数字时将以该频率每秒最多次数在 Web Worker 中录制 canvas 截图快照仅支持OffscreenCanvas的环境可用。对于 canvas 动画场景这是比整元素屏蔽更精细的折中方案。策略三压缩从体积维度削减存储基于 packFn 的单事件压缩rrweb 在 packages/packer 中提供了一个基于fflate的简单压缩函数可以直接作为packFn传入录制配置import { pack } from rrweb/packer; record({ emit(event) {}, packFn: pack, });其底层实现见 packages/packer/src/pack.ts先JSON.stringify事件再用zlibSync基于 fflate 的 deflate/zlib 实现压缩最后以二进制安全字符串输出。同时会给事件附加v: v1标记见 packages/packer/src/base.ts 中的MARK常量用于回放时识别压缩版本。从 packages/rrweb/src/record/index.ts 的eventProcessor可以看到packFn在每个事件通过emit输出前被调用也就是说每个 event 独立压缩。需要注意当启用跨域 iframe 录制并向父窗口传递事件passEmitsToParent时事件不会被packFn处理。回放时需要把packer.unpack作为unpackFn传入Replayerimport { unpack } from rrweb/packer; import { Replayer } from rrweb/replay; const replayer new Replayer(events, { unpackFn: unpack, });unpack的实现packages/packer/src/unpack.ts具备较强的健壮性先尝试按普通 JSON 解析兼容未压缩的历史数据再尝试按压缩数据解压并通过v MARK校验版本兼容性最后才抛出Unknown data format错误。这意味着你可以混合使用压缩与未压缩的数据只要数据本身格式合法。批量压缩更推荐的服务端方案基于packFn的单事件压缩以每个 event为单位进行这往往不能发挥 rrweb 录制数据易于压缩的优势——相邻事件之间尤其是连续的全量快照、样式表、长文本输入存在大量重复片段而单个小 JSON 的 zlib 压缩无法利用跨事件的冗余。因此文档更加推荐在服务端实现多个 event 的批量压缩例如将单次用户操作一个 session / 一次请求上下文产生的所有 event 合并为一个大块再压缩。对于 gzip、zlib 等压缩算法而言更大的输入块意味着更高的压缩比这在长会话场景下收益显著。策略四去冗只存一份相同的数据压缩之外另一个优化思路是去冗deduplication。为了在回放中准确模拟 hover 等效果rrweb 会尽可能地将 CSS 样式inline进录制数据即inlineStylesheet: true这是 packages/rrweb/src/record/index.ts 的默认值。可以想象如果使用 rrweb 录制大量用户对同一站点的访问每个 session 的录制数据中都会保存几乎完全相同的样式表内容——N 个用户就是 N 份拷贝。去冗的基本思路遍历录制数据识别包含样式表内容的事件例如快照中的stylesheet数据、增量中的样式变更将这部分内容提取出来单独保存一份按内容哈希去重回放时再通过映射关系把去冗后的内容还原回事件中。同样的思路也适用于全量快照FullSnapshot不同 session 的首次全量快照如果来自同一页面骨架其 DOM 结构大部分相同可以跨 session 提取公共部分仅存储一份显著降低存储总量。组合应用一套可落地的优化路线四类策略并非互斥实际项目中建议按先减量、再减频、后减体积的顺序组合屏蔽对长列表、SVG、JS 动画、canvas 动画等数据大户用blockClass/blockSelector/ignoreClass排除出录制范围packages/rrweb-snapshot/src/snapshot.ts 是判断的核心抽样用sampling关闭或降频次要事件——mousemove: false、mouseInteraction细粒度关闭、scroll/media调大节流阈值、input: last各观察器实现在 packages/rrweb/src/record/observer.ts压缩客户端可用packFnpackages/packer/src/pack.ts做兜底服务端对整段 session 批量压缩以获得更优压缩比去冗在存储层对样式表与全量快照做内容级去重。每一步优化都会带来回放精细度或实现复杂度的代价屏蔽会导致部分区域回放不可见、input: last会丢失逐键过程、批量压缩需要在回放前先整体解压。建议在接入时先评估真实数据量分布哪些事件占比最高再有针对性地启用对应策略并在每个阶段用真实录制数据验证回放效果最终得到数据量与回放质量的最优平衡点。赞分享前端可观测性开发工具【免费下载链接】rrwebrecord and replay the web项目地址https://gitcode.com/gh_mirrors/rr/rrweb点击查看免费下载相关推荐rrweb 存储优化实战从采样降频到压缩去重的完整方案rrweb 存储优化实战从采样降频到压缩去重的完整方案 在真实业务中接入 rrwebrecord and replay the web后一个常见问题是前端可观测性开发工具Docker-Mailserver存储优化终极指南从压缩到去重的完整解决方案Docker Mailserver存储优化终极指南从压缩到去重的完整解决方案 Docker Mailserver作为一款生产级的邮件服务器容器解决方案集成了后端通信云原生抽样Sampling完全指南抽样方法、抽样分布、中心极限定理与 Bootstrap抽样Sampling完全指南抽样方法、抽样分布、中心极限定理与 Bootstrap 本篇为开源教科书 Maths, CS AI Compendium文档教程知识库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价