首页   注册   登录
 aryu 最近的时间轴更新

aryu

V2EX 第 191373 号会员,加入于 2016-09-12 10:05:59 +08:00
aryu 最近回复了
113 天前
回复了 aryu 创建的主题 分享创造 聊聊我们开源的 web 录制与回放库: rrweb
@guyskk0x0 游戏机的例子是借用的一个开源的实现,基于 HTML 的。

canvas 目前没有处理,理论上可以通过 monkey patch 一些 canvas 的 API 来实现一个 canvasObserver,不过对 canvas 不太熟悉不确定是否可行。d3 如果是 SVG 的部分录制起来是没问题的,需要在给元素打快照的时候判断是否需要增加 SVG namespace。

比如哪些事件无法回放呢?我们现在的实现思路是视觉上的逻辑回放,所以只需要回放会对视觉产生影响的事件,其它的 JS 逻辑本身也不会回放,但是对 DOM 的改变会被录制下来。比较特殊的是 hover 没法用 JS 模拟,所以这部分我们通过增加一些 CSS 规则和控制样式类的添加 /移除来模拟。
@xichengh
前端主要负责产品内 web console 的开发,同时负来负责一些内部系统。开发过程中产出的一些通用前端工具我们也会开源出来。

技能上需要熟练使用 Typescript 或者能编写高质量的 Javascript 代码,有目前主流前端框架的使用经验。
除此之外对任何 web 相关领域有深入研究都可以作为加分项来试一试~

简历发给 LZ 就行
199 天前
回复了 autoxbc 创建的主题 JavaScript 我猜很多人都没真的用过 MutationObserver
排版好像出了些问题,我放在一个 gist 里了
199 天前
回复了 autoxbc 创建的主题 JavaScript 我猜很多人都没真的用过 MutationObserver
例子里面的打印不是很有利于观察实际发生的情况,我稍微修改了一下,增加了每次 callback 触发的打印和遍历 added node 时具体的 node 的打印。

```
<!DOCTYPE html>

<head>
<script>
const callback = mttns => {
console.log('callback here')
mttns.forEach(mttn => {
[...mttn.addedNodes].forEach(node => {
if (node.nodeType !== 1)
return;

console.log('added element type node', node)
if (node.querySelector('div p')) {
console.log('[found with selector "div p"]');
}
if (node.querySelector('div a')) {
console.log('[found with selector "div a"]');
}
});
});
};
const opts = { childList: true, subtree: true };
new MutationObserver(callback).observe(document, opts);
</script>
</head>

<body>
<div>
<p></p>
<script></script>
<a></a>
</div>
</body>

</html>
```

MutationObserver 的核心机制是“异步 + 批量”,主要是处于性能考虑,不过在使用上是容易造成一些误解。改动后的代码打印结果如下:

```
>>> callback here
added element type node <body>​…​</body>​
[found with selector "div p"]
added element type node <div>​…​</div>​
[found with selector "div p"]
added element type node <p>​</p>​
added element type node <script>​</script>​
>>> callback here
added element type node <a>​</a>​
```

可以看到以下现象:
1. 总共产生了两次 callback
2. 第一次 callback 添加了 body, div, p, script 四个 element node
3. 第二次 callback 添加了 a 这一个 element node
4. 如果你调整 script 标签的位置,你会发现 script 结束会立即触发一次 callback,这可能和 MutationObserver 具体的实现规则有关。

所以实际发生的情况是当第一次 callback 触发时,由于是异步的,所以第一次 callback 内包含的 4 个新增 node 已经存在于 DOM 中,query 'div p' 是可以查询到的,但是 a node 还没有插入,所以此时查询不到。
第二次 callback 时 a node 单独被插入,但是也不符合 'div p' 和 'div a' 的 query 规则,所以不触发打印。

MutationObserver 的异步批量回调机制确实需要比较细致的处理,最近开源的一个项目里也在一段[设计文档]( https://github.com/rrweb-io/rrweb/blob/master/docs/observer.zh_CN.md#%E6%96%B0%E5%A2%9E%E8%8A%82%E7%82%B9)里描述了一些这个机制导致的问题。
2018-07-13 21:55:17 +08:00
回复了 firhome 创建的主题 程序员 这个前端录屏原理是怎么实现的?有大佬知道吗?
不确定 fundebug 是怎么做的,不过看原理应该和国外一个很成熟的产品 logrocket 中的回放功能类似。

首先这类功能一般是为了用户行为追踪或者捕获异常前的操作信息,以 sdk 的形式集成到用户的应用中。
因此侵入性强、计算消耗大、网络开销多的方案都是不可能产品化的,上面讨论的 canvas 方案基本也就不可能。

具体来说可以把这个过程看作是 DOM 快照链。

第一步:对界面 DOM 进行一次全量快照。这一步还包括样式的收集、js 脚本的去除等,并通过一定的规则给当前的每个 DOM 元素标记一个 id。

第二步:监听所有可能对界面产生影响的事件,例如各类鼠标事件、输入事件、滚动事件、缩放事件等等,每个事件都记录 payload 和 target,target 是某个 DOM 元素的话就记录为第一步中的 id,这样比记录一个 css selector 数据量要小不少,同时还会定时获取鼠标的绝对坐标,有变化时也记录为一个事件。这样的每一次变化事件可以记录为一次增量的快照。

第三步:一些优化处理,比如浏览器端存一定量的增量快照后再一起发送到服务端,减少网络开销;也包括多次增量之后再进行一次全量,对齐真实状态。

第四步:再后台观看“录制”的时候,其实就是先用全量快照渲染出界面,然后顺着快照链走,按照时间戳把对应的修改重放到页面上,就形成了像视频一样的回放。

以上是我看 logrocket 的视频并且试用,然后逆向了一小部分 sdk 代码之后的分析,仅供参考。
关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3735 人在线   最高记录 5043   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.3 · 12ms · UTC 09:39 · PVG 17:39 · LAX 02:39 · JFK 05:39
♥ Do have faith in what you're doing.