须臾现码虫,一键纳乾坤——Hubble在微盟微前端中的应用
优采云 发布时间: 2022-04-29 20:30须臾现码虫,一键纳乾坤——Hubble在微盟微前端中的应用
通过Hubble的使用可以在一定程度上减少测试与研发在提bug、定位问题上的沟通的成本,测试同学不用大段文字描述,研发同学能够直观地通过回放观看bug出现的情况,以及根据接口或者报错信息快速定位问题以及复现bug。四、功能解析1.接入apm为了能记录到接口请求的记录,自行实现了一个rrweb插件,通过对浏览器原生的xhr 和 fetch api的覆写,以实现请求信息的AOP。鉴于已存在APM系统,所以不对接口请求的请求体和响应体进行记录,只记录下接口header中的apm trace id,在回放的时候可以通过这个trace id直接跳转到APM系统中,来查看请求信息,协助排查和定位问题。2.调试网页免登录Hubble的免登录功能,是通过采集cookies中的saasAuth token来实现的。在管理页面点击免登录查看时,会跳转到带hubble特殊查询参数的url,然后加载hubble时根据查询参数判断是免登录查看模式的话,将url中带有的token写入到cookies中,然后跳转到不带特殊参数的页面上,以实现跳过登录环节完成鉴权。需要在页面调用其他接口前完成Hubble的加载与判断。token有时效性,可能会出现失效情况。为了避免非手动退出来切换账号所产生的混乱,建议打开新的无痕窗口后粘贴免登录链接查看。3.裁剪功能在解决录制片段过长的角度上,借助归一化的概念,可以将裁剪到的所需时间段以外的事件,压缩到一段比较短的时间内去播放,这样就能实现近似裁剪功能了。
但是这属于比较取巧的方案,后续会尝试直接合并增量数据到全量snapshot数据上,这样既能减少采集到的数据量,同时减轻刚开始播放时的处理器计算压力。4.未捕获错误采集通过对window.onerror、unrejectionhandler和error事件的*敏*感*词*,并将采集到的错误信息以自定义事件的形式插入到rrweb的record序列中,在回放时就可以通过面板查看到错误信息,辅助定位问题。五、遇到的问题1.样式泄漏处理在开发使用过程中,Hubble的浏览器端出现了样式污染的问题,除了对自己编写的组件内的过于普遍的样式名进行更改之外,还需要对整个Hubble进行css的scope化。这里使用了部门内实现的postcss插件,在遍历css rules的时候(使用postcss的walkRules API),对规则内的所有css选择器前面,添加了一个当前包名 .${packageJson.name} 的一个类作为父选择器,同时在Hubble挂载的dom上也加上了这个className。同时,在一些使用了css变量的UI组件库,有些会将css变量定义在 :root 上,这是一个全局的伪类,如果不进行处理的话,css变量会泄漏并污染到全局。
于是在上述的postcss插件中也加入了:root 到 作用域类名替换的规则。2.打包加载优化为了优化初始化速度(更快进入录制状态)和防止大体积bundle加载带来的阻塞,且后续能支持插件化、sdk可拼装,打包形式上从iife改为system。这样在初始加载时能够优先加载主要功能并运行起来,ui部分进行延迟加载;同时拆解成system形式的包之后,后续可以根据配置来动态加载功能,预留出扩展能力。六、未来预计添加的功能1.开放接入能力基于systemjs的动态加载脚本的能力,Hubble可以通过配置来动态加载插件。后续考虑在这基础上开放出一些api以及自定义插件功能,比如可以使用hubble的addCustomEvent API来添加自定义事件,或者采集静态数据直接上传到hubble的后端。2.涂鸦评论功能在录制的记录上,有时候需要给录制到的内容进行标注评论以辅助传递信息,增强理解。现计划在后续添加涂鸦评论功能。涂鸦基于canvas,可以提交面板上编辑,记录下打标注的地方以及持续时长,也考虑添加图层功能来支持更复杂的标注能力。七、扩展阅读Hubble主要是围绕rrweb 这个dom录制框架进行开发的。
rrweb是通过MutationObserver API来*敏*感*词*页面上dom的变动,以及用户输入的各种操作事件进行捕获采集,然后通过rrweb的DOM序列化算法将DOM结构json化,以及事件行为的格式化,形成一个变动更新列表,然后在回放的时候,通过将序列化的dom数据通过rebuild,和事件行为的重放,重现在一个iframe沙盒中,来实现页面操作的回放。其中,rrweb主要有这些事件类型:dom加载完成、加载、全量快照、增量快照、元数据、自定义事件、插件事件。而其中的增量快照则有这些数据来源:dom Mutation、鼠标键盘滚轮触摸等操作、窗口resize、输入框输入、样式变动等。录制开始后,rrweb会将每次dom变动,*敏*感*词*到的事件,自定义触发事件等录制到的数据通过一个数组来保存,每个事件对应着一个事件对象,其中含有触发时的时间戳、事件类型、内容载体payload等。在rrweb上生成一个dom的全量快照时,会给当前的dom元素一个个分配一个id,用来记录和追踪其变化。当增量数据中dom的变动要apply到snapshot对应的dom树上时,会根据id查找出目标dom节点,将MutationObserver *敏*感*词*到的dom变化应用到数据模型上。
(rrweb维护了一个node Map,以方便快速查找到节点)当在播放器进行操作时,比如进行时间跳转(goto),会通过状态机和事件管道,先暂停再调用播放。调用播放函数时传入了跳转的timeOffset,这时会进行如下处理:暂停时会记录播放的最后event,然后再开始时,首先会计算出跳转后的时间偏移量,来定义一个基准时间戳(跳转后的时间戳)。对于小于基准时间戳的事件,会以同步的方式全部apply起来,而剩余的事件则是用定时器触发。同时,会把基准事件戳与上次播放的最后的event中含有的时间戳进行比对,如果往前跳则清除节点Map数据,以同步方式重新计算;如果是往后跳则将同步计算的结果合并到已有的节点Map上。在定时器的使用上,由于setInterval会受到性能等各方面影响,这种事件定时器在精度上不能满足需求。于是rrweb使用了requestAnimationFrame的API来作为定时器(机制上因为不受到eventloop的影响,精度能达到1ms级别),使用performance.now()来作为获取每次触发定时器callback的时间偏移量(减去初始值),从而准确地触发rrweb待播放List中的事件。八、结语不通过口述或者截图等方式、而是通过录屏的方式进行记录,同时可以记录接口等数据,这样可以在复现前端场景上节省沟通成本、快速定位问题,从而提高效率。我们也会在后续的迭代中,寻找合适的场景落地,尝试更多方案,助力开发提效。