Update zh_CN Docs (#384)
* update zh_CN guide, with latest API and options * add receipes * update receipes and guide * update #329 add links to README
This commit is contained in:
24
docs/recipes/canvas.zh_CN.md
Normal file
24
docs/recipes/canvas.zh_CN.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Canvas
|
||||
|
||||
Canvas 是一种特殊的 HTML 元素,默认情况下其内容不会被 rrweb 观测。我们可以通过特定的配置让 rrweb 能够录制并回放 Canvas。
|
||||
|
||||
录制时包含 Canvas 内的内容:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {},
|
||||
// 对 canvas 进行录制
|
||||
recordCanvas: true,
|
||||
});
|
||||
```
|
||||
|
||||
回放时对 Canvas 进行回放:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
UNSAFE_replayCanvas: true,
|
||||
});
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
**回放 Canvas 将会关闭沙盒策略,导致一定风险**。
|
||||
53
docs/recipes/custom-event.zh_CN.md
Normal file
53
docs/recipes/custom-event.zh_CN.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 自定义事件
|
||||
|
||||
录制时可能需要在特定的时间点记录一些特定含义的数据,如果希望这部分数据作为回放时的一部分,则可以通过自定义事件的方式实现。
|
||||
|
||||
开始录制后,我们就可以通过 `record.addCustomEvent` API 添加自定义事件:
|
||||
|
||||
```js
|
||||
// 开始录制
|
||||
rrweb.record({
|
||||
emit(event) {
|
||||
...
|
||||
}
|
||||
})
|
||||
|
||||
// 在开始录制后的任意时间点记录自定义事件,例如:
|
||||
rrweb.record.addCustomEvent('submit-form', {
|
||||
name: '姓名',
|
||||
age: 18
|
||||
})
|
||||
rrweb.record.addCustomEvent('some-error', {
|
||||
error
|
||||
})
|
||||
```
|
||||
|
||||
`addCustomEvent` 接收两个参数,第一个是字符串类型的 `tag`,第二个是任意类型的 `payload`。
|
||||
|
||||
在回放时我们可以通过监听事件获取对应的事件,也可以通过配置 rrweb-player 在回放器 UI 的时间轴中展示对应事件。
|
||||
|
||||
**获取对应事件**
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
|
||||
replayer.on('custom-event', (event) => {
|
||||
console.log(event.tag, event.payload);
|
||||
});
|
||||
```
|
||||
|
||||
**在 rrweb-player 中展示**
|
||||
|
||||
```js
|
||||
new rrwebPlayer({
|
||||
target: document.body,
|
||||
props: {
|
||||
events,
|
||||
// 自定义各个 tag 在时间轴上的色值
|
||||
tags: {
|
||||
'submit-form': '#21e676',
|
||||
'some-error': 'red',
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
72
docs/recipes/customize-replayer.zh_CN.md
Normal file
72
docs/recipes/customize-replayer.zh_CN.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 自定义回放 UI
|
||||
|
||||
当 rrweb Replayer 和 rrweb-player 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
|
||||
你可以通过以下几种方式从不同角度自定义回放 UI:
|
||||
|
||||
1. 使用 rrweb-player 时,通过覆盖 CSS 样式表定制 UI。
|
||||
2. 使用 rrweb-player 时,通过 `showController: false` 隐藏控制器 UI,重新实现控制器 UI。
|
||||
3. 通过 `insertStyleRules` 在回放页面(iframe)内定制 CSS 样式。
|
||||
4. 基于 rrweb Replayer 开发自己的回放器 UI。
|
||||
|
||||
## 实现控制器 UI
|
||||
|
||||
使用 rrweb-player 时,可以隐藏其控制器 UI:
|
||||
|
||||
```js
|
||||
new rrwebPlayer({
|
||||
target: document.body,
|
||||
props: {
|
||||
events,
|
||||
showController: false,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
实现自己的控制器 UI 时,你可能需要与 rrweb-player 进行交互。
|
||||
|
||||
通过 API 控制 rrweb-player:
|
||||
|
||||
```js
|
||||
// 在播放和暂停间切换
|
||||
rrwebPlayer.toggle();
|
||||
// 播放
|
||||
rrwebPlayer.play();
|
||||
// 暂停
|
||||
rrwebPlayer.pause();
|
||||
// 更新 rrweb-player 宽高
|
||||
rrwebPlayer.$set({
|
||||
width: NEW_WIDTH,
|
||||
height: NEW_HEIGHT,
|
||||
});
|
||||
rrwebPlayer.triggerResize();
|
||||
// 切换否跳过无操作时间
|
||||
rrwebPlayer.toggleSkipInactive();
|
||||
// 设置播放速度为 2 倍
|
||||
rrwebPlayer.setSpeed(2);
|
||||
// 跳转至播放 3 秒处
|
||||
rrwebPlayer.goto(3000);
|
||||
```
|
||||
|
||||
通过监听事件获得 rrweb-player 的状态:
|
||||
|
||||
```js
|
||||
// 当前播放时间
|
||||
rrwebPlayer.addEventListener('ui-update-current-time', (event) => {
|
||||
console.log(event.detail.payload);
|
||||
});
|
||||
|
||||
// 当前播放状态
|
||||
rrwebPlayer.addEventListener('ui-update-player-state', (event) => {
|
||||
console.log(event.detail.payload);
|
||||
});
|
||||
|
||||
// 当前播放进度
|
||||
rrwebPlayer.addEventListener('ui-update-progress', (event) => {
|
||||
console.log(event.detail.payload);
|
||||
});
|
||||
```
|
||||
|
||||
## 基于 rrweb Replayer 开发自己的回放器 UI
|
||||
|
||||
可以参照 [rrweb-player](https://github.com/rrweb-io/rrweb-player) 的方式进行开发。
|
||||
70
docs/recipes/dive-into-event.zh_CN.md
Normal file
70
docs/recipes/dive-into-event.zh_CN.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# 深入录制数据
|
||||
|
||||
录制数据是一组类型严格的 JSON 数据,通过熟悉其格式,可以更灵活的使用录制数据。
|
||||
|
||||
## 数据类型
|
||||
|
||||
每个 event 都拥有 `timestamp` 属性用于标记时间戳。
|
||||
|
||||
除此之外,也都拥有 `type` 属性标记 event 类型,其对应关系如下:
|
||||
|
||||
```
|
||||
type -> EventType.DomContentLoaded
|
||||
event -> domContentLoadedEvent
|
||||
|
||||
type = EventType.Load
|
||||
event -> loadedEvent
|
||||
|
||||
type -> EventType.FullSnapshot
|
||||
event -> fullSnapshotEvent
|
||||
|
||||
type -> EventType.IncrementalSnapshot
|
||||
event -> incrementalSnapshotEvent
|
||||
|
||||
type -> EventType.Meta
|
||||
event -> metaEvent
|
||||
|
||||
type -> EventType.Custom
|
||||
event -> customEvent
|
||||
```
|
||||
|
||||
其中 EventType 是 Typescipt 的 numeric enum,在运行时是从 0 开始的数字,其类型定义详见[列表](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L10)。
|
||||
|
||||
其中 incrementalSnapshotEvent 代表增量数据,其具体增量类型可以通过 `event.data.source` 字段进行判断:
|
||||
|
||||
```
|
||||
source -> IncrementalSource.Mutation
|
||||
data -> mutationData
|
||||
|
||||
source -> IncrementalSource.MouseMove
|
||||
data -> mousemoveData
|
||||
|
||||
source -> IncrementalSource.MouseInteraction
|
||||
data -> mouseInteractionData
|
||||
|
||||
source -> IncrementalSource.Scroll
|
||||
data -> scrollData
|
||||
|
||||
source -> IncrementalSource.ViewportResize
|
||||
data -> viewportResizeData
|
||||
|
||||
source -> IncrementalSource.Input
|
||||
data -> inputData
|
||||
|
||||
source -> IncrementalSource.TouchMove
|
||||
data -> mouseInteractionData
|
||||
|
||||
source -> IncrementalSource.MediaInteraction
|
||||
data -> mediaInteractionData
|
||||
|
||||
source -> IncrementalSource.StyleSheetRule
|
||||
data -> styleSheetRuleData
|
||||
|
||||
source -> IncrementalSource.CanvasMutation
|
||||
data -> canvasMutationData
|
||||
|
||||
source -> IncrementalSource.Font
|
||||
data -> fontData
|
||||
```
|
||||
|
||||
enum IncrementalSource 的定义详见[列表](https://github.com/rrweb-io/rrweb/blob/master/src/types.ts#L64)。
|
||||
5
docs/recipes/export-to-video.zh_CN.md
Normal file
5
docs/recipes/export-to-video.zh_CN.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# 转换为视频
|
||||
|
||||
rrweb 录制的数据是一种高效、易于压缩的文本格式,可以用于像素级的回放。但如果有进一步将录制数据转换为视频的需求,同样可以通过一些工具实现。
|
||||
|
||||
**TBD**
|
||||
65
docs/recipes/index.zh_CN.md
Normal file
65
docs/recipes/index.zh_CN.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 场景示例
|
||||
|
||||
> 除场景示例外,你可能还想通过[使用指南](../../guide.zh_CN.md)掌握 rrweb 常用 API,或是通过[设计文档](../)深入 rrweb 的技术细节。
|
||||
|
||||
## 场景列表
|
||||
|
||||
### 录制与回放
|
||||
|
||||
录制与回放时最常用的使用方式,适用于任何需要采集用户行为数据并重新查看的场景。
|
||||
|
||||
[链接](./record-and-replay.zh_CN.md)
|
||||
|
||||
### 深入录制数据
|
||||
|
||||
录制数据是一组类型严格的 JSON 数据,通过熟悉其格式,可以更灵活的使用录制数据。
|
||||
|
||||
[链接](./dive-into-event.zh_CN.md)
|
||||
|
||||
### 异步加载数据
|
||||
|
||||
当录制的数据较多时,一次性加载至回放页面可能带来较大的网络开销和较长的等待时间。这时可以采取数据分页的方式,异步地加载数据并回放。
|
||||
|
||||
[链接](./pagination.zh_CN.md)
|
||||
|
||||
### 实时回放(直播)
|
||||
|
||||
如果希望持续、实时地看到录制的数据,达到类似直播的效果,则可以使用实时回放 API。这个方式也适用于一些实时协同的场景。
|
||||
|
||||
[链接](./live-mode.zh_CN.md)
|
||||
|
||||
### 自定义事件
|
||||
|
||||
录制时可能需要在特定的时间点记录一些特定含义的数据,如果希望这部分数据作为回放时的一部分,则可以通过自定义事件的方式实现。
|
||||
|
||||
[链接](./custom-event.zh_CN.md)
|
||||
|
||||
### 回放时与 UI 交互
|
||||
|
||||
回放时的 UI 默认不可交互,但在特定场景下也可以通过 API 允许用户与回放场景进行交互。
|
||||
|
||||
[链接](./interaction.zh_CN.md)
|
||||
|
||||
### 自定义回放 UI
|
||||
|
||||
当 rrweb Replayer 和 rrweb-player 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
|
||||
[链接](./customize-replayer.zh_CN.md)
|
||||
|
||||
### 转换为视频
|
||||
|
||||
rrweb 录制的数据是一种高效、易于压缩的文本格式,可以用于像素级的回放。但如果有进一步将录制数据转换为视频的需求,同样可以通过一些工具实现。
|
||||
|
||||
[链接](./export-to-video.zh_CN.md)
|
||||
|
||||
### 优化存储容量
|
||||
|
||||
在一些场景下 rrweb 的录制数据量可能高于你的预期,这部分文档可以帮助你选择适用于你的存储优化策略。
|
||||
|
||||
[链接](./optimize-storage.zh_CN.md)
|
||||
|
||||
### Canvas
|
||||
|
||||
Canvas 是一种特殊的 HTML 元素,默认情况下其内容不会被 rrweb 观测。我们可以通过特定的配置让 rrweb 能够录制并回放 Canvas。
|
||||
|
||||
[链接](./canvas.zh_CN.md)
|
||||
19
docs/recipes/interaction.zh_CN.md
Normal file
19
docs/recipes/interaction.zh_CN.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 回放时与 UI 交互
|
||||
|
||||
回放时的 UI 默认不可交互,但在特定场景下也可以通过 API 允许用户与回放场景进行交互。
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
|
||||
// 允许用户在回放的 UI 中进行交互
|
||||
replayer.enableInteract();
|
||||
|
||||
// 禁用用户在回放的 UI 中进行交互
|
||||
replayer.disableInteract();
|
||||
```
|
||||
|
||||
rrweb 使用 CSS 的 `pointer-events: none` 属性禁用交互。
|
||||
|
||||
这能够让回放更加稳定,例如避免用户点击回放中的超链接发生跳转等。
|
||||
|
||||
如果你希望允许用户交互,例如用户可以在回放时在输入框中进行输入,那么就可以调用 `enableInteract` API,但需要对不稳定的场景自行加以处理。
|
||||
27
docs/recipes/live-mode.zh_CN.md
Normal file
27
docs/recipes/live-mode.zh_CN.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 实时回放(直播)
|
||||
|
||||
如果希望持续、实时地看到录制的数据,达到类似直播的效果,则可以使用实时回放 API。这个方式也适用于一些实时协同的场景。
|
||||
|
||||
使用 rrweb Replayer 进行实时回放时,需要传入 `liveMode: true` 配置,并通过 `startLive` API 启动直播模式。
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer([], {
|
||||
liveMode: true,
|
||||
});
|
||||
|
||||
replayer.startLive(FIRST_EVENT.timestamp - BUFFER);
|
||||
```
|
||||
|
||||
使用 `startLive` API 启动直播模式时,你可以传入一个可选参数,用于设置基线时间戳,这对于需要一定缓冲时间的直播场景非常有用。
|
||||
|
||||
例如录制时的第一个事件记录于 1500 这个时间点,实时回放时传入 `startLive(1500)` 就会让回放器将基线时间戳定为 1500,并用于计算后续事件的延迟时间。
|
||||
|
||||
但这有时会让实时回放看起来卡顿,因为数据的传输需要一定的时间(例如网络延迟),同时一些事件因为节流的性能优化会延迟发出(例如鼠标移动)。
|
||||
|
||||
因此我们可以通过 `startLive` 传入一个较小值的方式来提供一个缓冲时间,例如 `startLive(500)` 就会让回放总是延迟 1 秒播放。如果传输延迟小于 1 秒,则观看者不会感到卡顿。
|
||||
|
||||
启动直播模式后,可以通过 `addEvent` API 不断将最新的事件传入回放器中:
|
||||
|
||||
```js
|
||||
replayer.addEvent(NEW_EVENT);
|
||||
```
|
||||
102
docs/recipes/optimize-storage.zh_CN.md
Normal file
102
docs/recipes/optimize-storage.zh_CN.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 优化存储容量
|
||||
|
||||
在一些场景下 rrweb 的录制数据量可能高于你的预期,这部分文档可以帮助你选择适用于你的存储优化策略。
|
||||
|
||||
优化策略分为以下几类:
|
||||
|
||||
- 通过屏蔽 DOM 元素,减少录制的内容
|
||||
- 通过 sampling 配置抽样策略,减少录制的数据
|
||||
- 通过去冗、压缩,减少数据存储体积
|
||||
|
||||
## 屏蔽 DOM 元素
|
||||
|
||||
一些特定 DOM 元素可能会产生大量的录制数据,而这些数据未必是回放时关注的,这种情况下可以选择将这些 DOM 元素进行屏蔽,不录制其内容。
|
||||
|
||||
常见的大数据量 DOM 元素包括:
|
||||
|
||||
- 长列表
|
||||
- 复杂的 SVG
|
||||
- 包含 JS 控制动画的元素
|
||||
|
||||
## 抽样策略
|
||||
|
||||
录制时通过 sampling 配置可以让特定数据以抽样的形式减少录制频率:
|
||||
|
||||
**示例 1**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// 不录制鼠标移动事件
|
||||
mousemove: false
|
||||
// 不录制鼠标交互事件
|
||||
mouseInteraction: false,
|
||||
// 设置滚动事件的触发频率
|
||||
scroll: 150 // 每 150ms 最多触发一次
|
||||
// 设置输入事件的录制时机
|
||||
input: 'last' // 连续输入时,只录制最终值
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**示例 2**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// 定义不录制的鼠标交互事件类型,可以细粒度的开启或关闭对应交互录制
|
||||
mouseInteraction: {
|
||||
MouseUp: false,
|
||||
MouseDown: false,
|
||||
Click: false,
|
||||
ContextMenu: false,
|
||||
DblClick: false,
|
||||
Focus: false,
|
||||
Blur: false,
|
||||
TouchStart: false,
|
||||
TouchEnd: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## 压缩
|
||||
|
||||
### 基于 packFn 的单数据压缩
|
||||
|
||||
rrweb 内包含了基于 pako 的简单压缩 rrweb.pack,在录制时可以作为 `packFn` 传入。
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {},
|
||||
packFn: rrweb.pack,
|
||||
});
|
||||
```
|
||||
|
||||
回放时通用需要传入 rrweb.unpack 作为 `unpackFn` 传入。
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
unpackFn: rrweb.unpack,
|
||||
});
|
||||
```
|
||||
|
||||
### 批量压缩
|
||||
|
||||
基于 packFn 的单数据压缩以每个 event 数据为单位进行压缩,但这很多时候不能发挥 rrweb 录制数据易于压缩的优势。
|
||||
|
||||
因此**更加推荐**在服务端实现多个 event 的批量压缩,例如将单次用户操作产生的所有 event 数据进行一次压缩,对于 gzip 等压缩算法来说更为友好。
|
||||
|
||||
## 去冗
|
||||
|
||||
另一个优化存储容量的思路是去冗。
|
||||
|
||||
为了模拟 hover 等需求,rrweb 会尽可能的将 CSS 样式 inline 在录制数据中。
|
||||
|
||||
可以想象,如果使用 rrweb 录制每个用户对 github.com 的访问,则会在录制数据中保存大量重复的样式表内容。
|
||||
|
||||
可以通过遍历录制数据,将包含样式表的内容提取单独保存的方式,将这部分相同数据仅保存一份。
|
||||
|
||||
另一方面,全量快照类的数据也存在同样的问题,可以使用同样的思路去冗,减少存储总量。
|
||||
23
docs/recipes/pagination.zh_CN.md
Normal file
23
docs/recipes/pagination.zh_CN.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# 异步加载数据
|
||||
|
||||
当录制的数据较多时,一次性加载至回放页面可能带来较大的网络开销和较长的等待时间。这时可以采取数据分页的方式,异步地加载数据并回放。
|
||||
|
||||
rrweb 中用于实现异步加载数据的 API 非常简单直观:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
|
||||
replayer.addEvent(NEW_EVENT);
|
||||
```
|
||||
|
||||
只需要调用 `addEvent` 传入新的数据,rrweb 就会自动处理其中的时间关系,以最恰当的方式进行回放。
|
||||
|
||||
如果需要异步加载多个数据,只需这样使用:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
|
||||
for (const event of NEW_EVENTS) {
|
||||
replayer.addEvent(event);
|
||||
}
|
||||
```
|
||||
30
docs/recipes/record-and-replay.zh_CN.md
Normal file
30
docs/recipes/record-and-replay.zh_CN.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# 录制与回放
|
||||
|
||||
录制与回放时最常用的使用方式,适用于任何需要采集用户行为数据并重新查看的场景。
|
||||
|
||||
仅需一个函数调用就可以录制当前页面:
|
||||
|
||||
```js
|
||||
const stopFn = rrweb.record({
|
||||
emit(event) {
|
||||
// 保存获取到的 event 数据
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
你可以使用任何方式保存录制的数据,例如通过网络请求将数据传入至后端持久化保存,但请确保:
|
||||
|
||||
- 一组录制的数据按照 event.timestamp 中的时间戳从小至大保存
|
||||
- 完整保存数据,不缺失任何一个 event。
|
||||
|
||||
如果需要手动停止录制,可以调用返回的 `stopFn` 函数。
|
||||
|
||||
回放时只需要获取一段录制数据,并传入 rrweb 提供的 Replayer:
|
||||
|
||||
```js
|
||||
const events = GET_YOUR_EVENTS
|
||||
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user