前端性能优化的指标和工具

1,783 阅读7分钟

前端性能优化的指标和测量工具

本文主要介绍前端性能优化的指标和测量工具,因为性能优化是一把双刃剑,某些性能优化规则在某些场景下并不适用,所以我们需要借助一些工具和标准检验自己的优化是否正确

一、瀑布图

打开 Chrome, Network, 点击刷新按钮

image.png

1. 具体资源加载过程

image.png

  • Queueing: 浏览器在以下情况下将请求排入队列:

    • 有更高优先级的请求。
    • 已经打开了 6 个 TCP 连接,Chrome浏览器最多允许对同一个域名Host建立6个TCP连接,不同的浏览器有所区别。
    • HTTP/1.1中单个TCP连接,在同一时间只能处理一个http请求,HTTP2提供了多路传输功能,多个http请求,可以同时在同一个TCP连接中进行传输
    • 浏览器正在磁盘缓存中短暂分配空间
  • Stalled: 资源阻塞时间,请求会因为上面的任一个原因而阻塞

    • 浏览器本身对同一个域名的并发请求是有数量限制的,chrome是6个,如果当前的连接数超过浏览器的上限,那么其他的资源请求就会被阻塞。可以将资源放在不同的域名

    • js脚本会阻塞其他资源的下载,可以将js发在页面底部,或者将在script标签使用async 或者 defer, 脚本相对于页面的其余部分异步地执行

  • DNS Lookup: 浏览器正在解析请求的IP地址

    • 可以通过 DNS Prefetch,原理就是在 HTTP 建立之前,将 DNS 查询的结果缓存到系统/浏览器中,提升网页的加载效率
  • Initial connection. 浏览器和服务器建立连接的过程, tcp建立连接的三次握手时间

  • SSL(ssl协议加密): 安全验证,ssl 协商

  • Request sent: 发送请求的时间

  • Waiting (TTFB): 请求发出后等待服务器响应的时间

    • CDN 通过将资源部署到世界各地,使得⽤户可以就近访问资源,加快访问速度。要接⼊CDN,需要把⽹⻚的静态资源上传到CDN服务上,在访问这些资源时,使⽤CDN服务提供的URL。
  • Content Download: 下载资源的时间

    压缩资源,减小体积

2. 资源与资源直接关系,关键时间节点

image.png

资源与资源之间关系,如果发生了阻塞,资源是串行的,一个一个加载,可以让某些资源并行进行加载

蓝色的线(DOMContentLoaded) DOM 加载完成的时间

资源与资源(Load)页面所有资源加载完的时间

3.保存性能测试结果,方便后续继续使用

右键,点击 Save all as HAR with content,

SCII5DJ(MWB}3LQF9HBUMWL.png

二、交互体验指标

  • 帧率FPS(1秒60FPS)

    • 打开 chrome 调试工具 ctrl + shift + p

    image.png

    • 输入 frame

    image.png

  • 交互动作的反馈要在 1s 内完成

    • 压缩
    • loading 效果

三、RAIL 测量模型

1. 什么是 RAIL

  • Response 响应 用户进行一些操作,网站有没有及时给出一个反馈
  • Animation 动画
  • Idle 空闲
  • Load 加载

2. RAIL 评估标准

  • Response 响应:处理事件应在 50ms 以内完成

image.png 用户输入到给出反馈要在 100ms 以内,而我们真正做时间处理的事件没有 100ms,还要有一个时间对输入进行处理,这个时间保守估计在 50 毫秒

  • Animation 动画:每 10ms 产生一帧 1 秒 60 帧,约算 16.666ms 一帧,但浏览器绘制也需要时间,大概在 6ms 左右
  • Idle 空闲:尽可能增加空闲时间 Idle 和 Response 是相互应的,只有足够空闲,才有时间去处理响应
  • 加载:在 5s 内完成内容加载可以进行交互 加载->解析->渲染 设备、网络环境

四、性能测量工具

  • Chrome DevTools 开发调试、性能评测
  • Lighthouse 网站整体质量评估
  • WebPageTest 多测试地点,全面性能报告

1. 使用 Lighthouse 分析性能

// 安装
npm install -g lighthouse
// 测量
lighthouse 想要测量的链接

打开 chrome 开发者工具点击 Lighthouse

image.png

image.png

  • First Contentful Paint 表示文档中任一元素首次渲染的时间。(这个网站能不能打开)

    • 绿:0 ~ 2 秒
    • 黄:2 ~ 4 秒
    • 红:> 4 秒
  • Speed Index 速度指数,页面中可见内容多久能让用户看到

  • Largest Contentful Paint 所有可见的资源中最大的那个花了多久。(打开的这个网站是不是用户想访问的)

    • 绿:0 ~ 2.5 秒
    • 黄:2.5 ~ 4 秒
    • 红:> 4 秒
  • Time to Interactive 什么时候用户可以和你网站进行交互。(这个网站能不能用)

    • 绿:0 ~ 3.8 秒
    • 黄:3.8 ~ 7.3 秒
    • 红:> 7.3 秒
  • Total Blocking Time 总阻塞时间,这个总和是通过添加所有长任务的阻塞部分之间的First Contentful Paint 和 Time to Interactive 来计算的。任何执行时间超过50毫秒的任务都是一项漫长的任务。50 ms之后的时间是阻塞部分。

image.png

这十个截屏代表从用户开始访问,一直整个页面的显现

image.png

优化的建议

2. 使用 Chrome DevTools 分析性能

1) Network

资源压缩 image.png

我们可以看资源上下大小不一样,上面的 1.1MB 代表资源通过网络的实际大小,下面的 3.7MB 资源本身的大小,网络传输的大小可以实际传输大小不相同,服务器先对资源进行压缩,再进行解压

不使用缓存

image.png

自定义网络吞吐

image.png

image.png

image.png

选中自定的网络

2) Performance

image.png

点击实心圆开始记录,记录这个过程中页面所发生的一切包括的你的交互,都会被记录下来,直到点击结束

点击刷新,刷新页面,记录从页面开始进行刷新,到页面加载完发生的一切

image.png

image.png

这里内容很多,我们主要关心 Main(主线程),Timings(一些关键的时间节点)

3) Rendering

Rendering

ctrl + shift + p 输入 Rendering,勾选 Paint flashing 观察页面重绘情况

4) Performance monitor

性能检测

image.png

五、常用的性能测量 APIS

  • 关键时间节点(Navigation Timing,Resourse Timing)
  • 网络状态(Network APIs)
  • 客户端服务端协商(HTTP Client Hints) & 网页显示状态(UI APIs)

用户可交互时间

performance 很多的时间节点有关的属性都可以从 performance 对象上获取到

// load 事件后触发
window.addEventListener('load', (event) => {
    // Time to Interacrtive 可交互时间
    let timing = performance.getEntiesByType('navigation')[0];
    // 计算 tti = domInteractive - fetchStart 
    // 这两个值是一个时间戳,请求发出和可进行交互
    let tti = timing.domInteractive - timing.fetchStart;
});

获取一些耗时的长任务

// 通过 PerformanceObserver 得到所有的 long tasks 对象
let observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        console.log(entry);
    }
});

// 监听 long tasks
observer.observe({ entryTypes: ['longtask'] })

观察用户是否在当前页面

let vEvent = 'visibilitychange';
if (document.webkitHidden != undefined) {
    // webkit 事件名称
    vEvent = 'webkitvisibilitychange';
}
function visibilityChanged() {
    if (document.hiddent || document.webkitHidden) {
        console.log("Web page is hidden");
    } else {
        console.log("Web page is visibile");
    }
}
document.addEventListener(vEvent, visibilityChanged);

判断用户的网络状态

可以根据用户的网络状态请求不同清晰度的图片

let connection = navigator.connection || navigator.mozConnect || navigator.webkitConnection;
let type = connection.effectiveType;
connection.addEventListener('change', () => {
    console.log("connection type changed from" + type + " to " + connection.effectiveType);
})
  • DNS 解析耗时: domainLookupEnd - domainLookupStart
  • TCP 连接耗时: connectEnd - connectStart
  • SSL 安全连接耗时: connectEnd - secureConnectionStart
  • 网络请求耗时 (TTFB): responseStart - requestStart
  • 数据传输耗时: responseEnd - responseStart
  • DOM 解析耗时: domInteractive - responseEnd
  • 资源加载耗时: loadEventStart - domContentLoadedEventEnd
  • First Byte时间: responseStart - domainLookupStart
  • 白屏时间: responseEnd - fetchStart
  • 首次可交互时间: domInteractive - fetchStart
  • DOM Ready 时间: domContentLoadEventEnd - fetchStart
  • 页面完全加载时间: loadEventStart - fetchStart
  • http 头部大小: transferSize - encodedBodySize
  • 重定向次数:performance.navigation.redirectCount
  • 重定向耗时: redirectEnd - redirectStart
  • 过滤阻塞的资源
// 获取所有资源  
const res = window.performance.getEntriesByType('resource');  
  
// 过滤出阻塞渲染的资源  
const blocking =   res.filter(({renderBlockingStatus}) =>  
      renderBlockingStatus === 'blocking');

深入浅出 Performance 工具 & API Chrome可以识别渲染阻塞资源了