前言
上篇文章最初提到了咱们能够通过performance的一些属性对性能做统计,咱们会发现performance
对象下有十分多的属性,远不止上篇文章提到的DOMContentLoaded
与Load
这两个事件。
或者你在浏览器控制台见过它们这些身影:DCL
、LCP
、FP
、FCP
、L
这里的DCL
与L
就是咱们上篇文章介绍的DOMContentLoaded
与Load
这两个事件,那剩下的LCP
、FP
、FCP
又别离代表什么呢?
在晚期前端三剑客的时代或者当初的服务端渲染,DCL
与L
的确能够很好地掂量首屏内容展现工夫,但对于古代各种框架流行的单页利用,因为都是通过JS操作DOM向页面增加次要内容,DCL
和L
事件就不能很好地掂量首屏显示工夫了。
于是有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>
从这张图上咱们能够看到此时DCL
比Load
先触发,并且很显著能够看到在两者之前多了个图片的下载过程。
所以两者触发的先后顺序并不是固定的,如果页面有许多内部资源须要加载,那么load
事件会后触发,如果页面内容较多,内部资源较少,那么load
事件可能先触发。
为了应答当初框架流行的单页利用新增了上面这几个指标,它们关注的不再是页面的加载过程,而是页面的渲染过程。
FP与FCP
为了不便,这两个放一起讲:
FP,全称 First Paint, 代表首次渲染的工夫点,即首次视觉变动产生的工夫点。前端开发者常常谈到的白屏工夫(用户看不到任何内容)就是用户拜访网页到 FP 的这段时间。
FCP,全称 First Contentful Paint,代表首次 DOM 内容 渲染的工夫点,DOM 内容 能够是文本、图像(包含背景图像)、
<svg>
元素或非红色的<canvas>
元素。
简略点了解就是FCP
事件指渲染出第一个内容的事件,而FP
指渲染出第一个像素点,渲染出的货色可能是内容,也可能不是。
⚠️须要留神的是,FCP
肯定不会比FP
晚触发,但可能会一起触发,绝大多数状况是FP在FCP之前触发!
几种场景
第一种: 无FP
是不是很奇怪,怎么会有这种状况?其实咱们下面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"> </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
,因为没有内容
耗时计算
// FPconst fp = performance.getEntries('paint').filter(entry => entry.name == 'first-paint')[0].startTime;// FCPconst fcp = performance.getEntries('paint').filter(entry => entry.name == 'first-contentful-paint')[0].startTime;
FP与DCL的触发程序
浏览器不肯定等到所有的DOM都解析完再开始渲染,如果DOM节点少,浏览器会加载完再渲染,然而如果节点很多,浏览器解析一部分节点后就会开始渲染(这时候就会触发FP)。也就是说,当须要渲染的节点数少的时候,DCL会在FP后面;当须要渲染的节点数很多时候,DCL会在FP前面。
当初来说,绝大部分的我的项目都是FP
在DCL
之前触发,这样用户能够更快的看到页面内容。
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个别须要按以下步骤:
- 先进行首次内容绘制 (FCP)
- 沿时间轴正向搜寻时长至多为 5 秒的宁静窗口,其中,宁静窗口的定义为:没有long task且不超过两个正在解决的网络 GET 申请
- 沿时间轴反向搜寻宁静窗口之前的最初一个长工作,如果没有找到长工作,则在 FCP 步骤进行执行
- 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()
来代替和调整height
和width
属性。 - 如需使元素可能到处挪动,能够用
transform: translate()
来代替和调整top
、right
、bottom
或left
属性。
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);
如果这篇文章有帮忙到你,❤️关注+点赞❤️激励一下作者,文章公众号首发,关注 前端南玖
第一工夫获取最新文章~