基于rrweb实现网页远控功能


目录

点击折叠/展开
  • 目录
  • 简介
  • 设计
    • 序列化
      • 序列化中的特殊处理
      • 唯一标识
    • 增量快照
      • Mutation Observer
        • 新增节点
        • 移除节点
        • 属性变化覆盖写
      • 鼠标移动
        • 时间逆推
      • 输入
        • 人为交互
        • 程序设置
    • 回放
      • 高精度计时器
      • 补全缺失节点
      • 模拟 Hover
      • 从任意时间点开始播放
    • 沙盒
      • iframe sandbox
      • 避免链接跳转
      • iframe 样式设置
  • 结构
    • rrweb-snapshot
    • rrweb
    • rrweb-player
  • 缺陷
    • 非常规节点录制
    • 无法进行局部录制
    • 直播时对网络稳定性的要求较高
    • 在一定程度上使原网页性能降低
  • 远控
    • 设计思路
      • 屏幕共享
      • 远程控制

简介

rrweb'record and replay the web' 的简写,旨在利用现代浏览器所提供的强大 API 录制并回放任意 web 界面中的用户操作。
设计初衷是为了解决我们在客户环境 debug 时遇到的?些问题。大多数产品通常部署在客户的内?环境中,因此?旦出现问题只能通过各类远程操作?具登?客户环境中进? debug,操作的空间和时间都?常有限。如果不幸遇到?些偶发性的问题,复现就变得难上加难,debug 更是?从谈起。
在这种情况下,前端的异常监控及对应数据的收集显得?常重要,但是传统的收集错误栈信息的?式并不能给我们提供?够的信息?于定位问题。

设计

序列化

如果仅仅需要在本地录制和回放浏览器内的变化,那么我们可以简单地通过深拷贝 DOM 来实现当前视图的保存。例如通过以下的代码实现(使用 jQuery 简化示例,仅保存 body 部分):

// record
const snapshot = $("body").clone();
// replay
$("body").replaceWith(snapshot);

我们通过将 DOM 对象整体保存在内存中实现了快照。

但是这个对象本身并不是可序列化的,因此我们不能将其保存为特定的文本格式(例如 JSON)进行传输,也就无法做到远程录制,所以我们首先需要实现将 DOM 及其视图状态序列化的方法。在这里我们不使用一些开源方案例如 parse5 的原因包含两个方面:

  1. 我们需要实现一个“非标准”的序列化方法,下文会详细展开。
  2. 此部分代码需要运行在被录制的页面中,要尽可能的控制代码量,只保留必要功能。

序列化中的特殊处理

之所以说我们的序列化方法是非标准的是因为我们还需要做以下几部分的处理:

  1. 去脚本化。被录制页面中的所有 JavaScript 都不应该被执行,例如我们会在重建快照时将 script 标签改为 noscript 标签,此时 script 内部的内容就不再重要,录制时可以简单记录一个标记值而不需要将可能存在的大量脚本内容全部记录。
  2. 记录没有反映在 HTML 中的视图状态。例如 输入后的值不会反映在其 HTML 中,而是通过 value 属性记录,我们在序列化时就需要读出该值并且以属性的形式回放成
  3. 相对路径转换为绝对路径。回放时我们会将被录制的页面放置在一个