我花 2 天把 rrweb 原理扒干净了,顺便讲清楚前端「录屏回放」怎么做
最近在看前端监控方案,绕不开 rrweb。
一开始以为只是“录个 DOM + 回放”,真翻完源码才发现,这玩意设计得很克制。
这篇不是 API 教程,而是我理解 rrweb 之后,对它核心实现思路的一次拆解。
先说结论:rrweb 干的不是“录屏”
如果你以为 rrweb 是:
把页面录成视频 → 出问题再回放
那就完全误会了。
rrweb 做的事情是:
记录页面结构 + 页面变化 + 用户操作,再按时间重放
所以它能做到:
- 数据量可控
- 可倍速 / 拖动
- 精确复现 Bug
一、rrweb 的整体思路,其实很简单
我理解下来,rrweb 就三件事:
- 先拍一张“全家福” (初始 DOM 快照)
- 只记后面的变化(DOM / 输入 / 鼠标)
- 按时间一帧帧还原
结构大概是这样:
录制(record) → 事件流 → 回放(replay)
看起来简单,但坑都在细节里。
二、为什么一定要「初始快照」
一开始我也疑惑:
既然能监听 DOM 变化,为什么不从空页面开始 replay?
后来发现不行。
原因很现实:
- 回放时用户页面早没了
- JS 不可重跑
- 网络状态完全不同
所以 rrweb 的第一步一定是:
把当前页面完整“冻住”
但注意,它不是存 HTML 字符串,而是:
把 DOM 树序列化成 JSON
这一步,直接决定了后面所有设计。
三、rrweb 最关键的设计:NodeId
这是我觉得 rrweb 最聪明的地方。
❌ 为什么不用 DOM Path
html > body > div:nth-child(3) > span
这种路径有三个问题:
- DOM 稍微一变就废
- 定位成本高
- 性能不友好
✅ rrweb 的做法:给每个节点发「身份证」
Node ⇄ nodeId
一旦某个 DOM 被序列化过,它就有了一个全局唯一 id。
之后所有事件,只认 id,不认 DOM。
这一步,直接把「回放稳定性」拉满。
四、DOM 变化到底怎么记?
rrweb 用的是 MutationObserver,但不会原样保存 mutation。
它做的是一层“翻译”。
比如新增节点
rrweb 记录的是:
- 父节点是谁
- 插入了什么
- 插在谁前面
{
type: 'child-added',
parentId,
node,
nextId
}
这样回放时,才能100% 还原位置。
删除节点 / 属性变化也是同理
它存的是“语义”,不是浏览器原始事件。
五、一个非常容易踩的坑:input 事件
MutationObserver 监听不到:
- input.value
- checkbox.checked
因为这些是 property,不是 attribute。
所以 rrweb 会单独监听:
input / change / composition
并且还会:
- mask 密码
- 处理中文输入法
- 区分 radio / checkbox
这一块不做全,回放基本就废了。
六、为什么 mousemove 不能原样记录?
这个很好理解:
mousemove 真的太多了。
如果你每一帧都记,一分钟就是几千条事件。
rrweb 的解法是:
- 不记“每一次”
- 只记“最近一次”
- 固定频率采样
这样数据量直接降一个数量级。
七、回放为什么一定要用 iframe?
这个点我一开始没想明白,后来才意识到很重要。
用 iframe 能解决的事情包括:
- CSS 完全隔离
- position: fixed 正确
- 不污染宿主页面
- 不执行原页面 JS
一句话总结:
rrweb 回放的是页面“状态”,不是页面“逻辑”
八、rrweb 的回放不是 setTimeout
如果用 setTimeout,你会很快发现:
- 暂停难
- 拖动时间轴几乎不可能
rrweb 用的是:
requestAnimationFrame + 时间轴推进
本质是:
当前时间能执行哪些事件,就执行哪些
这也是它能支持倍速和拖动的原因。
九、rrweb 最核心的一条原则
看完源码我最大的感受是:
rrweb 非常不信任浏览器
所以它:
- 不执行 script
- 不触发真实事件
- 所有变化都由 replay engine 控制
也正因为这样,回放结果才稳定。
十、rrweb 在真实项目里的用法
一般不会全程录:
- 错误前 N 秒开始
- 出错立即停止
- 只上传关键片段
配合:
- error stack
- 用户环境
- 性能数据
定位问题效率会直接拉满。
最后一点个人感受
rrweb 并不复杂,但非常工程化。
它的厉害之处不是炫技,而是:
- 每一步都在权衡成本
- 每一个设计都有明确取舍
如果你在做:
- 前端监控
- 复杂交互系统
- 编辑器 / 可回放系统
rrweb 这套思路,真的值得完整读一遍。