9

挑战月薪30K | 前端性能优化的12 条建议(干货收藏)

 3 years ago
source link: https://segmentfault.com/a/1190000038578594
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者:九思

你好,我是九思,来自腾讯前端技术部,擅长前端监控、工程化相关技术。此篇文章将围绕前端性能优化中监控问题展开讨论。

首先我们要知道,页面打开快不快,不是在电脑或手机上的打开速度说了算,也不是测试同学测试的结果说了算,而是真实用户使用的时候说了算。

那么如何去监控用户真实使用时的页面性能呢?本文将做细致介绍(建议收藏)

前端监控需要注意什么?


页面上线后,我们最关心用户打开页面的速度,通常就是首屏。

页面加载离不开静态资源的加载,包括 js、css、img、video、font 等,在如今盛行 SPA 的场景尤为重要,比如活动页面会有很多图片,我们通常会开发一些模板,由产品/运营同学来配置,而图片多大合适是比较难确定的,网速越来越快,大家对清晰度要求也越来越高,此时就可以通过监测这些图片的加载速度来酌情优化。

API 请求

数据是页面中相当重要的元素,可以说没有数据,你的页面几乎没有使用价值(纯静态除外)。当然这里我们只能粗暴的监控整个请求的总时间,纯前端无法监控各个阶段时间,但这对于线上应用也很重要。

实际上线后,不同的应用可能会有不同的测速诉求,比如:视频从加载到播放的时间,此时可以自定义一些测速点,利用之前讲述的打点方式来上报。

如何监控静态资源?


这块其实还是比较简单的,只需要利用 PerformanceResourceTiming 即可,并且它的兼容性极高,可以覆盖到几乎所有场景。

图片

实际监控时,可以分两种场景,如果支持 performanceObserver 可以实时监听,否则使用定时器方式,此外需要将此代码放到页面最顶层,否则无法监控到这段代码之前的资源加载。

 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 监控


关于 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,只要在 JSnewImage 对象就能发起请求,而且还没有阻塞问题,在没有js的浏览器环境中也能通过 img 标签正常打点,这是其他类型的资源请求所做不到的。

在所有图片中1px x 1px 大小,gif 体积最小,相较 BMP/PNG,可以节约41%/35%的网络资源,所以适用 gif 相对是最佳选择。

页面的性能数据,每次访问都会有,如果你的项目 pv 有一定量级,那么处理起来就会相当耗费资源,而且这些数据我们最终是求平均值或者分位值,所以没必要全量上报。那么我们可以在上报前做一些限流处理。


除了以上这几点,前端监控的实操中我们还应该考虑到如何处理这些性能数据,主要有取中位数、平均值、分位数等做法,由于篇幅有限此处不做详细介绍。

最后,如果这篇文章给你带来些许有价值的理解,欢迎点赞、分享,更多内容可翻阅我的付费专栏《前端性能优化12问》。

点击链接查看详情:https://ke.sifou.com/course/1...


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK