Web前端最新优化指标:FP、FCP、FMP、LCP、TTI、CLS、FID、FPS等

加载性能指标

  • DCL(DOMContentLoaded),DOM解析完毕,不包含css、图像和子框架的完成加载。
  • load(Onload Event),它代表页面中依赖的所有资源加载完的事件。
  • FP(First Paint),表示渲染出第一个像素点。FP一般在HTML解析完成或者解析一部分时候触发。
  • FCP(First Contentful Paint),表示渲染出第一个内容,这里的“内容”可以是文本、图片、canvas。
  • FMP(First Meaningful Paint),首次渲染有意义的内容的时间,“有意义”没有一个标准的定义,FMP的计算方法也很复杂。
  • LCP(largest contentful Paint),最大内容渲染时间。

DCL事件

  • DOMContentLoaded事件,当 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式表、图像和子框架的完成加载。

  • 可以通过注册回调监听该事件

document.addeventListener('DOMContentLoaded', function() {}, false)
  • 计算方式:
const dclTime = performance.timing.domContentLoadedEventEnd - performance.timing.domContentLoadedEventStart

load事件

  • Onload Event代表页面中依赖的所有资源:DOM、图片、CSS、Flash等都加载完,window.onload注册的回调就会在load事件触发时候被调用。

  • 计算方式:

const loadTime = performance.timing.loadEventEnd - performance.timing.loadEventStart;

FP

  • FP(First Paint):首次绘制时间,这个指标用于记录页面第一次绘制像素的时间。
  • FP指渲染出第一个像素点,渲染出的东西可能是内容,也可能不是
  • 计算方法:
const fp = performance.getEntriesByType('paint').filter(entry => entry.name == 'first-paint')[0].startTime;

FCP

  • FCP(First Contentful Paint):首次内容绘制时间,这个指标用于记录页面首次绘制文本、图片、非空白 Canvas 或 SVG 的时间。
  • 计算方法:
const fcp = performance.getEntriesByType('paint').filter(entry => entry.name == 'first-contentful-paint')[0].startTime;

FMP

  • FMP(First Meaningful Paint),首次渲染有意义的内容的时间,从页面加载开始,到大部分或者主要内容已经在首屏上渲染的时间点。“有意义”没有一个标准的定义,FMP的计算方法也很复杂。
  • 计算方式:
// FMP计算比较复杂,lighthouse的计算的大体思路是,将页面中最大布局变化后的第一次渲染事件作为FMP事件,并且计算中考虑到了可视区的因素。
// FMP计算过于复杂,没有现成的performance API,如果希望在监控中上报这个指标,可以自己使用MutationObserver计算。

LCP

  • LCP(Largest Contentful Paint):最大内容绘制时间,用于记录视窗内最大的元素绘制的时间,该时间会随着页面渲染变化而变化,因为页面中的最大元素在渲染过程中可能会发生改变,另外该指标会在用户第一次交互后停止记录。
  • 计算方法:
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

白屏和首屏

  • 白屏时间 = 地址栏输入网址后回车 – 浏览器出现第一个元素
  • 白屏结束时间 = FP事件触发时间
  • 首屏时间 = 地址栏输入网址后回车 – 浏览器第一屏渲染完成
  • 首屏结束时间 = FCP事件触发时间 或 FMP、LCP

FP和FCP的关系

  • 浏览器渲染的界面可能是“内容”,例如文本,也可能不是“内容”,比如一个背景为红色的div标签。
  • FCP事件指渲染出第一个内容的事件而FP指渲染出第一个像素点,渲染出的东西可能是内容,也可能不是。
  • 有节点不一定有渲染,如果没有任何样式,是没有界面的,也不需要渲染。下面代码就没有FP事件
<html>
  <head>
    <meta charset="UTF-8">
    <title>no FP</title>
  </head>
  <body>
    <div></div>
  </body>
</html>
  • 下面代码,会渲染界面,因此会触发FP事件,但是不会触发FCP,因为没有内容
<html>
<head>
    <meta charset="UTF-8">
    <title>has FP, no FCP</title>
    <style>
        div {
            width: 1px;
            height: 1px;
            background-color: red;
        }
    </style>
</head>
<body>
    <div></div>
</body>
</html>

注意:渲染的操作一定是发生在视口内的,对于视口外不可见的内容,不会触发“Paint”操作,比如下面代码,不会触发FP事件。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>no FP</title>
    <style>
        div {
            position: absolute;
            left: -99999px;
            width: 1px;
            height: 1px;
            background-color: red;
            float: left;
        }
    </style>
</head>
<body>
    <div></div>
</body>
</html>

通过上面对FP和FCP的介绍,可以知道,如果html本身有内容(文本、图片)或者js脚本很快能创建内容,那么FP和FCP会一起触发。否则FP比FCP提前触发。FP肯定不会在FCP后面出现,因为渲染出内容,一定也渲染出了像素。

可交互时间

TTI

  • TTI(Time to Interactive):首次可交互时间。这个指标计算过程略微复杂,它需要满足以下几个条件:
  1. 从 FCP 指标后开始计算;
  2. 持续 5 秒内无长任务(执行时间超过 50 ms)且无两个以上正在进行中的 GET 请求;
  3. 往前回溯至 5 秒前的最后一个长任务结束的时间。

– 计算方式:

const timeToInteractive = performance.timing.domInteractive - performance.timing.fetchStart

FID

FID(First Input Delay):首次输入延迟时间,记录在 FCP 和 TTI 之间用户首次与页面交互时响应的延迟。
– 计算方式:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('fid', entry.processingStart - entry.startTime);
  }
});
observer.observe({type: 'first-input', buffer: true});

稳定性指标

CLS

  • CLS(Cumulative Layout Shift):是对在页面的整个生命周期中发生的每一次意外布局变化的最大布局变化得分的度量,布局变化得分越小证明你的页面越稳定。

听起来有点复杂,这里做一个简单的解释:

  • 不稳定元素:一个非用户操作但发生较大偏移的可见元素称为不稳定元素。
  • 布局变化得分:元素从原始位置偏移到当前位置影响的页面比例 * 元素偏移距离比例
  • 计算方式:
import {getCLS} from 'web-vitals';
getCLS(console.log);
  • 网站应努力使 CLS 分数小于 0.1。减少CLS的方法,参考文章:页面视觉稳定性之CLS

流畅性指标

FPS

  • Chrome DevTool 中有一栏 Rendering 中包含 FPS 指标,但目前浏览器标准中暂时没有提供相应 API ,只能手动实现。这里需要借助 requestAnimationFrame 方法模拟实现,浏览器会在下一次重绘之前执行 rAF 的回调,因此可以通过计算每秒内 rAF 的执行次数来计算当前页面的 FPS。
  • FPS过低会让用户感觉卡顿,因此这个计算可以用来监控页面卡顿情况。

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注