做者:九思
你好,我是九思,来自腾讯前端技术部,擅长前端监控、工程化相关技术。此篇文章将围绕前端性能优化中监控问题展开讨论。css
首先咱们要知道,页面打开快不快,不是在电脑或手机上的打开速度说了算,也不是测试同窗测试的结果说了算,而是真实用户使用的时候说了算。前端
那么如何去监控用户真实使用时的页面性能呢?本文将作细致介绍(建议收藏)bootstrap
页面上线后,咱们最关心用户打开页面的速度,一般就是首屏。跨域
页面加载离不开静态资源的加载,包括 js、css、img、video、font 等,在现在盛行 SPA 的场景尤其重要,好比活动页面会有不少图片,咱们一般会开发一些模板,由产品/运营同窗来配置,而图片多大合适是比较难肯定的,网速愈来愈快,你们对清晰度要求也愈来愈高,此时就能够经过监测这些图片的加载速度来酌情优化。浏览器
数据是页面中至关重要的元素,能够说没有数据,你的页面几乎没有使用价值(纯静态除外)。固然这里咱们只能粗暴的监控整个请求的总时间,纯前端没法监控各个阶段时间,但这对于线上应用也很重要。性能优化
实际上线后,不一样的应用可能会有不一样的测速诉求,好比:视频从加载到播放的时间,此时能够自定义一些测速点,利用以前讲述的打点方式来上报。网络
这块其实仍是比较简单的,只须要利用 PerformanceResourceTiming 便可,而且它的兼容性极高,能够覆盖到几乎全部场景。框架
实际监控时,能够分两种场景,若是支持 performanceObserver 能够实时监听,不然使用定时器方式,此外须要将此代码放到页面最顶层,不然没法监控到这段代码以前的资源加载。dom
const typeList = \['script', 'link', 'img'\]; // const staticTime = {}; const dealTime = (entries) => { for (let i = 0, l = entries.length; i < l; i++) { const entry = entries\[i\]; if (typeList.indexOf(entry.initiatorType) !== -1) { staticTime\[entry.name\] = entry.connectEnd - entry.connectStart; } } } if (typeof window.PerformanceObserver === 'function') { const observer = new window.PerformanceObserver((list) => { dealTime(list.getEntries()); }); observer.observe({ entryTypes: \['resource'\] }); } else { setInterval(() => { const allEntries = performance.getEntriesByType('resource'); const entries = allEntries.slice(allEntries.length); dealTime(entries); }, 5000); }
entry 部分数值前端性能
connectEnd: 32.63499999593478
connectStart: 32.63499999593478
decodedBodySize: 160302
domainLookupEnd: 32.63499999593478
domainLookupStart: 32.63499999593478
duration: 37.54000000481028
encodedBodySize: 23876
entryType: "resource"
fetchStart: 32.63499999593478
initiatorType: "link"
name: "https://stackpath.bootstrapcdn.com
nextHopProtocol: "h2"
redirectEnd: 0
redirectStart: 0
requestStart: 44.60999999719206
responseEnd: 70.17500000074506
responseStart: 65.40999999560881
secu reConnectionStart: 32.63499999593478
serverTiming:[]
startTime: 32.63499999593478
transferSize: 23971
workerStart: 0
关于 API 的监控,能够采用重写 XHR 或者 fetch,这样能够适用任何的框架、请求库。时间计算则是经过打点的方式,若是只是固定项目监控,也能够直接采用打点的方式。若是采用重写的方式,不只能够监控请求的时长,还能够监控请求的成功失败率。
打点最简单的方式:
const startTime = Date.now(); fn() // 假设这里是同步执行 const timeCycle = Date.now() - startTime; // fn的执行耗时
除了以上这几点,前端监控的实操中咱们还应该考虑到上报、限流以及如何处理这些性能数据。
点击连接查看详情:https://ke.sifou.com/course/1...
发送请求咱们很容易想到适用 fetch / XHR,固然也可使用自动发起请求的 HTML 标签,好比 script、link、img。上报数据虽然能够拿来分析页面的真实运行数据,但有一点要注意的是:不能影响当前页面的运行或最小程度的影响。
是否能够直接用 fetch/XHR 呢?答案是否认的,由于上报的域名和页面的域名基本是不一样的,因此这里须要能够前端跨域的方式。
说到跨域,浏览器的 src 属性标签基本均可以,到底用哪一个呢?原则上要适用对页面影响最小的那个,诸如 Script、link 这些标签以前有讲述,他们都会对页面的运行形成影响。
而 img 变成了较为合适的方式,构造图片打点不只不用插入DOM,只要在 JS 中 new 出 Image 对象就能发起请求,并且尚未阻塞问题,在没有js的浏览器环境中也能经过 img 标签正常打点,这是其余类型的资源请求所作不到的。
在全部图片中1px x 1px 大小,gif 体积最小,相较 BMP/PNG,能够节约41%/35%的网络资源,因此适用 gif 相对是最佳选择。
页面的性能数据,每次访问都会有,若是你的项目 pv 有必定量级,那么处理起来就会至关耗费资源,并且这些数据咱们最终是求平均值或者分位值,因此不必全量上报。那么咱们能够在上报前作一些限流处理。
除了以上这几点,前端监控的实操中咱们还应该考虑到如何处理这些性能数据,主要有取中位数、平均值、分位数等作法,因为篇幅有限此处不作详细介绍。
最后,若是这篇文章给你带来些许有价值的理解,欢迎点赞、分享,更多内容可翻阅个人付费专栏《前端性能优化12问》。
点击连接查看详情:https://ke.sifou.com/course/1...