网站性能优化--性能指标及采集

3,227 阅读3分钟

引言

在平时工作中可能会遇到用户反馈:“哥们,你们的网站感觉很卡啊!”。这种来自用户的吐槽对前端同学可以说是直击心灵的冲击。此时就应该好好想想如何让用户不再出现这样的吐槽呢。首先就是指标化的了解自己的网站。

常用的衡量指标

可以结合两张图

第一张图是浏览器加载整个页面的时间线,第二张图则是这个是Google力推的指标,主要从4个视觉反馈阶段来描述页面性能。

总结一下常用的性能指标

  • 白屏时间:白屏时间是指浏览器从响应用户输入网址地址,到浏览器开始渲染内容的时间。
  • 首屏时间:首屏时间是指浏览器从响应用户输入网络地址,到首屏内容渲染完成的时间。 一般是首屏中的图片加载完毕的时候,我们认为是首屏结束的时间点。
  • 完全加载时间:DOM Tree 构建完成后,开始加载网页资源,资源完全加载完成后,从加载开始到此为网页的完全加载时间。
  • 可交互时间 (TTI):用户第一次可以和界面进行交互的时间
  • 慢会话 Long Tasks:RAIL有在100毫秒内相应用户输入的要求。如果响应超过这个时间就是慢会话
  • FPS:渲染帧率,动画的卡顿感

如何采集指标数据

Performance_API

PerformanceTiming中有许多指标,选取几个比较常用的。

  • PerformanceTiming.responseStart:返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。这个可以用来反映服务器或者是CDN响应的指标。
  • PerformanceTiming.domInteractive:返回当前网页DOM结构结束解析、开始加载内嵌资源时间,用户可以开始输入交互的时间点
  • PerformanceTiming.loadEventEnd: 整个页面加载结束的时间点

白屏时间的采集

可以用 window.performance.getEntriesByType('paint') 返回结果就是FP和FCP

image.png

首屏时间的采集

首屏时间需要从两块去衡量,一块是图片的加载,一块是dom的渲染。 图片的加载时间可以使用 window.performance.getEntriesByType('resource') 看一下返回的结果

image.png
需要判断initiatorType,取出responseEnd。

dom部分则用MutationObserver来监听dom变化。

另外考虑到是首屏,就需要配合getBoundingClientRect来判断元素是否在首屏内。 最后将两部分时间取较大值即可

拓展一下,如果你的首屏有其他资源会你也希望确认是否会大于图片的加载,可以参考 不同资源的加载时间的获取

TTI的采集

tti采集的库使用非常简单

import ttiPolyfill from './path/to/tti-polyfill.js';

ttiPolyfill.getFirstConsistentlyInteractive(opts).then((tti) => {
  // Use `tti` value in some way.
});

长任务的收集

const subscribeBtn = document.querySelector('#subscribe');

subscribeBtn.addEventListener('click', (event) => {
  // Event listener logic goes here...

  const lag = performance.now() - event.timeStamp;
  if (lag > 100) {
    ga('send', 'event', {
      eventCategory: 'Performance Metric'
      eventAction: 'input-latency',
      eventLabel: '#subscribe:click',
      eventValue: Math.round(lag),
      nonInteraction: true,
    });
  }
});

FPS

由于requestAnimationFrame会在每一帧渲染前被调用,所以fps的计算就依赖于他。

var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
  
var loop = function () {
    var now = Date.now();
    var fs = (now - lastFameTime);
    var fps = Math.round(1000 / fs);
  
    lastFameTime = now;
    allFrameCount++;
    frame++;
  
    if (now > 1000 + lastTime) {
        //算出一秒左右的时间内总共渲染了多少帧
        var fps = Math.round((frame * 1000) / (now - lastTime));
        frame = 0;
        lastTime = now;
    };
  
    window.requestAnimationFrame(loop);
}
 
loop();

参考资料

www.cnblogs.com/wmhuang/p/1… www.jianshu.com/p/456e6eff5… www.cnblogs.com/coco1s/p/80…