前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【前端监控】静态资源测速&错误上报

【前端监控】静态资源测速&错误上报

作者头像
神仙朱
发布2021-09-09 15:00:56
4.3K0
发布2021-09-09 15:00:56
举报
文章被收录于专栏:Vue源码 & 前端进阶体系

小东西快快学快快记,大知识按计划学,不拖延

继续监控内容总结,今天总结的是前端如何监控静态资源的加载情况,并进行数据上报

本文分为3个部分

1、监控静态资源重要性

2、静态资源测速上报

3、静态资源出错上报

静态资源监控重要性

一个页面的加载快慢,最重要的指标就是静态资源的加载速度了吧。你拼了命得对代码进行优化几十ms,结果静态资源一个不爽就给你耗了几百ms。

所以监控页面静态资源加载情况是十分有必要的。让我们更加全面评估页面的健康情况。

当应用静态资源加载总是缓慢或者出错,会进行告警,这时候马上去排查,是 cdn出了问题还是 资源有问题,就可以减少问题影响时间

静态资源缓慢和失败可是会直接影响用户体验和留存的

庆幸有监控的例子

之前我们上线了一个活动,我们自己验证没有问题。过了一会,静态资源告警就来了,原来是中国移动网络下,该cdn加载有问题,导致图片都加载不出来,所以我们才紧急切换cdn又发布了一版。

如果没有告警,我们哪里会知道什么鬼网络下会出现什么鬼异常。

什么中国移动,联通,电信,铁通,长城一堆网络,又不可能一个个去看,一个个看还存在偶然性。

而且说不定下次不是网络问题了,是xxxx偏门手机资源加载出错,那你可没有办法了吧

你想想如果没有资源告警,难道需要等用户来告诉你吗,想多了,人直接划走了。我淘宝买东西出问题都懒得和商家说…

监控什么静态资源

js , css , 图片,字体,video,audio

静态资源测速上报

1基本原理

这里我们会使用 performance.getEntries() ,它可以获取到页面所有的静态资源和接口请求

我们这次是为了处理静态资源,所以可以使用

代码语言:javascript
复制
performance.getEntriesByType('resource')

来过滤得到页面的静态资源,如js css img 等

对于单个资源,我们能获取到的信息是这些

根据上面的这些信息,我们可以清楚页面的加载情况

但是需要注意的是

使用 performance.getEntries() 获取资源的时候,可能并不能一下子拿到页面所有的资源,因为资源请求也不是一次性加载完的,就像懒加载的图片

所以我们还需要监听资源的动态载入

具体我们会使用 PerformanceObserver 对资源进行监听。

下面我们看一下这个api的使用例子,我们动态插入一个js,看是否能监听到如下

可以看到木有任何问题

兼容性

可以看到这比我们使用了两个api,来看下他们的兼容性

可以看到 PerformanceObserver 比 getEntries 兼容性差一些。ie全线不支持

2上报什么数据

除了我们会上报getEntris 中拿到的这些数据

我们还需要上报

3问题一览

虽然我们现在以这两个api 可以完成我们的功能,但是仍然存在一些问题需要解决

1、IE 对 PerformanceObeserver 完全不支持

那要怎么办,不管ie 了吗

当然不是

我们会使用一个定时器,循环定时3秒去手动获取资源

performance.getEntries()

这时候有个问题,循环 getEntries(),那不是每次循环获取到的资源有重复的吗??

是的,所以我们在其中加入了一个 资源截取标记位,表示当前已经收集的资源的长度

因为getEntries 获取到的资源列表顺序是一直固定的,所以每次我们调用一次getEntries,就可以把当前已经截取到的位置存起来,下次从这个位置后开始截取

比如这样

代码语言:javascript
复制
let currentResLen = 0;
setInterval(() => {
 const entrys = performance.getEntriesByType('resource');

  const currentRes = entrys.slice(currentResLen);

 currentResLen += currentRes.length;
},300);

2、浏览器保存资源数据有限

浏览器保存的资源信息是有大小限制的,超过一定数量,剩下的资源就算加载,也不会被记录。performance.getEntries() 就获取不到了。

比如在 chrome 中,最大缓冲资源数是 250个,超过这个数目后,资源无法被记录。

比如我加载了500张图片

使用 getEntries 获取资源的时候,只获取到了 250个

所以我们需要及时清除缓冲区

具体做法是

对缓冲区进行监听,当缓冲区满了之后,就清空资源

代码语言:javascript
复制
performance.onresourcetimingbufferfull = () => {
   performance.clearResourceTimings();
};

但是直接清空是有一定风险的,如果其他开发者想在页面想获取资源,发现死活获取不到,又不知道你这里的清空逻辑,就会困扰到别人....

所以这里清空缓存的时候,最好在控制台输出一些信息,用于提示开发者

另外前面我们说的,我们会有一个 资源截取标记位,用于记录已经截取的资源数量长度

这里清空缓存区的时候,标志位也要相应重置

3、无法判断资源成功失败

从 performance.getEntries 获取的资源列表中,无法判断资源是否加载成功失败

我们这部分只负责上报 资源的 加载速度,错误的资源不应该包含在内,所以需要剔除发生错误的资源。

错误的资源,我们会另外处理

现在可以知道的是

发生错误的 script 和 link 标签,并不会出现在在 getEntries 获取的资源列表中

但是 img 错误,仍然会出现在其中,如果不处理,会导致错误图片误报成功的情况

所以这里的处理是,对错误图片缓存起来,使用 getEntries 获取到资源列表的时候,把错误的图片过滤就可以了

怎么拿到错误的图片呢

1、获取已经加载的错误图片(可能在我们获取资源之前已经加载错误了)

2、监听全局错误事件,拿到错误的图片

具体逻辑做法如下

这里的图片处理逻辑 和我另一篇文章一样,大家可以参考一下,图片错误重载

代码语言:javascript
复制
const ErrImgList = [];

// 监听动态的图片错误
function watchImgError(params) {
 window.document.addEventListener(
   'error',
   (event) => {
     const target = event.target
     const url = target.src

     // 发生错误的图片存起来,因为错误的也会放在 entries 中,用来过滤
     if (target.nodeName === 'IMG') {
       ErrImgList.push(url);
     }
   },
   true // 设置为 true 表示捕获
 );
}

// 处理已经加载错误的图片
function observeStatic() {
 document.querySelectorAll('img').forEach((node) => {
   const lazySrc =
     node.getAttribute('data-src') || 
     node.getAttribute('lazy-src');

   if (!lazySrc) {
      // 加载完成 complete = true,naturalWidth=0 表示图片没高度,那就是加载失败
     if (element.complete && element.naturalWidth === 0) {
       ErrImgList.push(node.src);
     }
   }
 });
}

function reportResource(params) {
 performance.getEntries().forEach((entry) => {
   const { name } = entry;

   //   错误的图片不上报测速
   if (ErrImgList.indexOf(name) > -1) {
     return;
   }

   // 上报资源测速数据
 });
}

4什么时候上报数据

1、window.onload 上报

window.onload() 会在页面完全载入(包括静态资源完成)后触发,所以在这里可以上报一波

2、监听资源加载 再逐个上报

前面总体上报了一波之后,动态增加的资源,可以动态单个上报

5基本流程

可能画得不太规范,但是样子大概是这样

静态资源出错上报

上面我们对资源的加载速度数据进行了上报,我们还需要对错误的资源进行上报

因为 速度 和 错误 不是一个维度的数据,所以我们需要分开上报

1基本原理

使用全局监听错误事件,并设置 第三个参数 为 true,表示捕获,可以捕获到 页面中资源加载错误的情况

代码语言:javascript
复制
window.addEventListener('error',error,true)

拿到的错误信息如下

之前监听图片错误用于剔除资源测速上报,就是插在这里处理的,并不会监听两次。

2上报什么数据

错误上报的数据就不像 加载速度那样那么多,基本是下面三个

什么时候上报

监听错误事件回调内进行上报

3基本流程

代码参考

https://gitee.com/hoholove/study-code-snippet/blob/master/LOGGER/assetSpeed.js

最后

资源上报我们就已经总结完了,总体不难,就大概用两个api,但是其中还是会涉及兼容和优化的处理细节,总体来说难度不大

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵, 如果有任何描述不当的地方,欢迎后台联系本人,领取红包

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神仙朱 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档