乐趣区

关于前端:性能优化之详解各种指标

前言

上篇文章最初提到了咱们能够通过 performance 的一些属性对性能做统计,咱们会发现 performance 对象下有十分多的属性,远不止上篇文章提到的 DOMContentLoadedLoad这两个事件。

或者你在浏览器控制台见过它们这些身影:DCLLCPFPFCPL

这里的 DCLL就是咱们上篇文章介绍的 DOMContentLoadedLoad这两个事件,那剩下的 LCPFPFCP 又别离代表什么呢?

在晚期前端三剑客的时代或者当初的服务端渲染,DCLL 的确能够很好地掂量首屏内容展现工夫,但对于古代各种框架流行的单页利用,因为都是通过 JS 操作 DOM 向页面增加次要内容,DCLL 事件就不能很好地掂量首屏显示工夫了。

于是有 FP、FCP、FMP 被提出来,它们关注的不是 加载 ,而是 渲染,因而能更好地体现用户看到的状况。

FP、FCP 这两个指标尽管表白了渲染的事件,但对“用户关注的内容”没有体现,比方首屏渲染进去一个背景,或者一个 loading,可能对于用户来说和白屏区别不大。FMP 尽管体现了“要害内容”的因素,但它是简单的、含糊的,甚至是谬误的,并不能精确辨认页面次要内容的加载机会。

起初 LCP 指标被提出来,示意“用于度量视口中最大的内容元素何时可见”,它用来代替 FMP,表征页面的要害元素何时能够被用户看到。

除了加载性能,还有可交互工夫、稳定性指标、流畅性指标,在不同的业务场景都能够被监控用来作为晋升用户体验的根据。

性能相干

下面咱们提到了各种性能相干的事件,那么它们各种代表的含意是什么呢?

要害事件

名词 全称 解释
FP firstPaint 首次绘制
FCP firstContentfulPaint 首次内容绘制
LCP largestContentfulPaint 最大内容绘制
DCL domContentLoaded dom 内容解析实现
L loaded 页面的 load 事件

DCL(DOMContentLoaded)

当初始的 HTML 文档被齐全加载和解析实现之后,DOMContentLoaded 事件被触发,而无需期待样式表、图像和子框架的齐全加载。

事件监听

document.addEventListener('DOMContentLoaded', (event) => {console.log('DOM 齐全加载以及解析')
});

耗时计算

performance.timing.domContentLoadedEventStart - performance.timing.fetchStart

Load

load 事件在整个页面及所有依赖资源如样式表和图片都已实现加载时触发。它与 DOMContentLoaded 不同,后者只有页面 DOM 加载实现就触发,无需期待依赖资源的加载。

事件监听

window.addEventListener('load', (event) => {console.log('页面加载实现');
});

耗时计算

performance.timing.loadEventEnd - performance.timing.fetchStart

DCL 与 Load 触发的先后顺序

很多人可能会误以为 Load 的触发肯定会在 DCL 之后,尽管绝大多数咱们看到的的确是这样,但你从两者的 MDN 解释上来看,DCL关注的时 HTML 文档的加载与解析,而 Load 只关注资源的加载,所以两者触发的先后顺序并不是相对的。

比方上面两种状况:

第一种: 页面非常简单,没有引入任何内部资源

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="container">
        
    </div>

</body>
</html>

从图中能够看到此时的 Load 触发在 DCL 之前,这是因为 load 不蕴含对文档解析的工夫

第二种: 咱们引入一张图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <img src="https://imgservices-1252317822.image.myqcloud.com/coco/s06012023/9ac85415.g0q5wz.png" class="zan_icon" />
    </div>

</body>
</html>

从这张图上咱们能够看到此时 DCLLoad先触发,并且很显著能够看到在两者之前多了个图片的下载过程。

所以两者触发的先后顺序并不是固定的,如果页面有许多内部资源须要加载,那么 load 事件会后触发,如果页面内容较多,内部资源较少,那么load 事件可能先触发。

为了应答当初框架流行的单页利用新增了上面这几个指标,它们关注的不再是页面的 加载 过程,而是页面的 渲染 过程。

FP 与 FCP

为了不便,这两个放一起讲:

FP,全称 First Paint, 代表 首次渲染的工夫点 ,即首次视觉变动产生的工夫点。前端开发者常常谈到的 白屏工夫 (用户看不到任何内容)就是 用户拜访网页到 FP 的这段时间

FCP,全称 First Contentful Paint,代表 首次 DOM 内容 渲染的工夫点 DOM 内容 能够是文本、图像(包含背景图像)、<svg> 元素或非红色的 <canvas> 元素。

简略点了解就是 FCP 事件指渲染出第一个内容的事件,而 FP 指渲染出第一个像素点,渲染出的货色可能是内容,也可能不是。

⚠️须要留神的是,FCP肯定不会比 FP 晚触发,但可能会一起触发,绝大多数状况是 FP 在 FCP 之前触发!

几种场景

第一种: 无 FP

是不是很奇怪,怎么会有这种状况?其实咱们下面 DCLLoad那里的第一个案例就呈现了这种状况

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="container">
        
    </div>

</body>
</html>

页面上有节点但没有款式,很显然这种状况是不须要渲染页面的,所以也就没有FP

当然这里须要留神的是这里的节点不包含一些本身可见的节点(比方 img、input、video 等)

还有一种状况就是 如果要渲染的内容在视口之外,那么也不会触发 FP

第二种: 有 FP 无 FCP

同时为了验证第一种说法的留神点,这里我就写一个 input 来试试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <input type="text" />
    </div>

</body>
</html>

从这里咱们就能发现,此时页面只会触发FP,因为没有内容

耗时计算

// FP
const fp = performance.getEntries('paint').filter(entry => entry.name == 'first-paint')[0].startTime;

// FCP
const fcp = performance.getEntries('paint').filter(entry => entry.name == 'first-contentful-paint')[0].startTime;

FP 与 DCL 的触发程序

浏览器不肯定等到所有的 DOM 都解析完再开始渲染,如果 DOM 节点少,浏览器会加载完再渲染,然而如果节点很多,浏览器解析一部分节点后就会开始渲染(这时候就会触发 FP)。也就是说,当须要渲染的节点数少的时候,DCL 会在 FP 后面;当须要渲染的节点数很多时候,DCL 会在 FP 前面。

当初来说,绝大部分的我的项目都是 FPDCL之前触发,这样用户能够更快的看到页面内容。

LCP

LCP,全称 Largest Contentful Paint,依据页面首次开始加载的工夫点(即 first started loading,能够通过 performance.timeOrigin 失去)来报告可视区域内可见的 最大图像或文本块 实现渲染的绝对工夫

LCP 评分

为了提供良好的用户体验,咱们应致力将最大内容绘制工夫管制在 2.5 秒 或更短。

LCP 蕴含哪些元素类型

  • <img>元素
  • <image><svg>元素内的元素
  • <video>带有海报图像的元素(应用海报图像加载工夫)
  • 具备通过函数加载的背景图像的元素url()(而不是 CSS 突变)
  • 蕴含文本节点或其余内联级文本元素子元素的块级元素。

随着更多钻研的进行,将来可能会增加其余元素

如何确定页面的 LCP 元素

这里能够通过 performance 面板,在 Timings 这一行找到 LCP,点击它再找到上面的 summary,就能找到LCP 对应的节点元素了。

耗时计算

new PerformanceObserver((entryList) => {for (const entry of entryList.getEntries()) {console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

体验相干

谷歌始终十分重视网站的用户体验,挪动敌对性,页面加载速度和 HTTPS 是 Google 曾经应用的页面排名因素,而 2020 年,谷歌将 Core Web Vitals 新纳入的用户体验指标。

TTI

TTI 全称Time to Interactive 它用于测量页面从开始加载到次要子资源实现渲染,并可能疾速、牢靠地响应用户输出所需的工夫。

测量步骤

测量 TTI 个别须要按以下步骤:

  1. 先进行 首次内容绘制 (FCP)
  2. 沿时间轴正向搜寻时长至多为 5 秒的宁静窗口,其中,宁静窗口 的定义为:没有 long task 且不超过两个正在解决的网络 GET 申请
  3. 沿时间轴反向搜寻宁静窗口之前的最初一个长工作,如果没有找到长工作,则在 FCP 步骤进行执行
  4. TTI 是宁静窗口之前最初一个长工作的完结工夫(如果没有找到长工作,则与 FCP 值雷同)

为了不便了解,能够对照这张图

优良指标

为了提供良好的用户体验,网站在一般挪动硬件上进行测试时,应该致力将可交互工夫管制在 5 秒以内。

TBT

TBT 全称 Total Blocking Time,它次要是用于度量 FCP 和 TTI 之间的总的阻塞工夫。

只有存在long task(在主线程上运行超过 50 毫秒 (ms) 的工作),主线程就会被视为“阻塞”。咱们说主线程被“阻塞”,因为浏览器无奈中断正在进行的工作。因而,如果用户在长时间工作中的确与页面进行交互,则浏览器必须期待工作实现能力响应 *。*

优良指标

测量 TBT 能够应用谷歌 Lighthouse

为了提供良好的用户体验,在 均匀挪动硬件 上进行测试时,网站应致力使总阻塞工夫低于200 毫秒

CLS

CLS 全称 Cumulative Layout Shift 累积布局偏移,它用来测量整个页面生命周期内产生的所有意外布局偏移中最大一连串的 布局偏移分数

CLS 详情

只有可视区域中可见元素的起始地位(例如,元素在默认书写模式下的顶部和左侧地位)在两帧之间产生了变更,该 API 就会报告 layout-shift 条目。这样的元素被视为 不稳固元素

请留神,只有当现有元素的起始地位产生变更时才算作布局偏移。如果将新元素增加到 DOM 或是现有元素更改大小,则不算作布局偏移,前提是元素的变更不会导致其余可见元素的起始地位产生扭转。

CLS 分数

浏览器在计算 布局偏移分数 时,会查看可视区域大小和两个已渲染帧之间的可视区域中 不稳固元素 的位移。布局偏移分数是该位移的两个度量的乘积:影响分数 间隔分数(两者定义如下)。

布局偏移分数 = 影响分数 * 间隔分数

优良指标

为了提供良好的用户体验,网站应该致力将 CLS 分数管制在 0.1 或以下。为了确保您可能在大部分用户的访问期间达成倡议目标值,一个良好的测量阈值为页面加载的 第 75 个百分位数,且该阈值同时实用于挪动和桌面设施。

这里须要留神的是在写动画时优先思考应用 CSS transform属性,因为它可能在不触发布局偏移的状况下为元素设置动画:

  • transform: scale() 来代替和调整 heightwidth属性。
  • 如需使元素可能到处挪动,能够用 transform: translate() 来代替和调整 toprightbottomleft属性。

web-vitals

为了更精确的统计性能数据,能够应用 web-vitals 库来测量各项性能指标

能够获取的指标有:CLS、FID、LCP、以及 FCP、TTFB

import {getCLS, getFID, getLCP} from 'web-vitals'

getCLS(console.log);
getFID(console.log);
getLCP(console.log);

如果这篇文章有帮忙到你,❤️关注 + 点赞❤️激励一下作者,文章公众号首发,关注 前端南玖 第一工夫获取最新文章~

退出移动版