rrweb 录制存储优化实战:DOM 屏蔽、sampling 抽样、压缩与去冗全指南
前端可观测性开发工具【免费下载链接】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),仅供参考

相关新闻

Pandoc `--embed-resources` 内联 SVG 与 class 属性合并机制解析:从命令测试 9652 看源码实现

Pandoc `--embed-resources` 内联 SVG 与 class 属性合并机制解析:从命令测试 9652 看源码实现

Pandoc --embed-resources 内联 SVG 与 class 属性合并机制解析:从命令测试 9652 看源码实现 【免费下载链接】pandoc Universal markup converter 项目地址: https://gitcode.com/gh_mirrors/pa/pandoc 导读 本文以 pandoc 仓库中编号 9652 的命令测试&…

2026/9/21 15:36:42 阅读更多 →
Apache SkyWalking 集成 ActiveMQ Classic 监控:基于 JMX Prometheus Exporter 与 OpenTelemetry Collector 的完整方案

Apache SkyWalking 集成 ActiveMQ Classic 监控:基于 JMX Prometheus Exporter 与 OpenTelemetry Collector 的完整方案

Apache SkyWalking 集成 ActiveMQ Classic 监控:基于 JMX Prometheus Exporter 与 OpenTelemetry Collector 的完整方案 【免费下载链接】skywalking APM, Application Performance Monitoring System 项目地址: https://gitcode.com/gh_mirrors/sk/skywalking …

2026/9/21 15:36:42 阅读更多 →
Vitess v23.0.6 变更解读:VRLog 功能正式移除与 `--vreplication-enable-http-log` 标志弃用指南

Vitess v23.0.6 变更解读:VRLog 功能正式移除与 `--vreplication-enable-http-log` 标志弃用指南

Vitess v23.0.6 变更解读:VRLog 功能正式移除与 --vreplication-enable-http-log 标志弃用指南 【免费下载链接】vitess Vitess is a database clustering system for horizontal scaling of MySQL. 项目地址: https://gitcode.com/gh_mirrors/vi/vitess 本指…

2026/9/21 15:36:42 阅读更多 →

最新新闻

淘宝排名靠前技巧揭秘:3个源码级优化点,面试必问的底层逻辑

淘宝排名靠前技巧揭秘:3个源码级优化点,面试必问的底层逻辑

淘宝排名靠前技巧揭秘:3个源码级优化点,面试必问的底层逻辑 官方文档堆砌术语,读完还是不会用?这行混久了都知道,真正的硬核知识往往藏在底层实现里。今天不扯虚的,直接拆解淘宝搜索排名的核心逻辑。很多开发者在面试中被问倒,不是不懂业务,而是不懂…

2026/9/22 18:07:24 阅读更多 →
5分钟吃透Reveal源码,手写实现核心逻辑不踩坑

5分钟吃透Reveal源码,手写实现核心逻辑不踩坑

5分钟吃透Reveal源码,手写实现核心逻辑不踩坑 面试被问“Reveal.js 源码是怎么实现页面切换动画的”,你答得上来吗?别慌,很多后端转全栈的兄弟都栽在这。不是让你背代码,而是得懂那套 手写实现…

2026/9/22 18:07:24 阅读更多 →
3步手写实现quicksort,彻底告别排序崩溃焦虑

3步手写实现quicksort,彻底告别排序崩溃焦虑

3步手写实现quicksort,彻底告别排序崩溃焦虑 上周凌晨两点,线上接口突然超时,CPU飙到100%。翻日志一看,全是 java.lang.OutOfMemoryError 和递归栈溢出的 StackOverflowError…

2026/9/22 18:07:24 阅读更多 →
3招搞定爱在星光里性能瓶颈,图解原理告别StackTrace报错

3招搞定爱在星光里性能瓶颈,图解原理告别StackTrace报错

3招搞定爱在星光里性能瓶颈,图解原理告别StackTrace报错 凌晨两点,服务器报警响了,我抓起电脑一看,CPU飙到95%,日志里全是红色的StackTrace。这种报错一堆看不懂的情况,每个后端开发都经历过。别慌,今天咱们不聊虚的,直接…

2026/9/22 18:07:24 阅读更多 →
3CDAEMON乱码速查手册:从堆栈到源码的性能突围

3CDAEMON乱码速查手册:从堆栈到源码的性能突围

3CDAEMON乱码速查手册:从堆栈到源码的性能突围 面对满屏红色的 StackTrace,是不是感觉脑子瞬间宕机?尤其是当 3CDAEMON 相关的日志输出变成一堆 ? 或 �…

2026/9/22 18:07:24 阅读更多 →
CF人物模型底层逻辑拆解:版本升级API变更保姆级教程

CF人物模型底层逻辑拆解:版本升级API变更保姆级教程

CF人物模型底层逻辑拆解:版本升级API变更保姆级教程 版本升级后 API 全变了?别慌,CF人物系统的底层映射没变。 很多老哥在接手项目时,一跑代码就报错,参数对不上,对象引用丢失。 这篇保姆级教程,带你从内存堆栈角度,彻底搞懂 CF…

2026/9/22 18:06:23 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/22 8:51:04 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →