❝成长第一课:你没那么多观众,不必过多在意别人的眼光❞
大家好,我是「柒八九」。
在前几天,我们写了,关于如何利用fetchpriority
对页面资源进行优先级的处理。
然后,我也承诺大家也会有关于如何对一个网站进行优化分析。但是,在私下和朋友聊天中发现,其实大家对Chrome
浏览器的性能评价指标不是很熟悉,索性就先写几篇关于性能指标的文章。
还有,之前我们写过浏览器相关
的知识点,如果想了解该系列文章(「浏览器相关」),可以参考我们已经发布的文章。如下是往期文章。
好了,天不早了,干点正事哇。
性能指标 | 中文全称 | 描述 |
---|---|---|
FP | 首次绘制 | 浏览器「首次」在屏幕上绘制像素的时间点,即页面开始显示内容的时间。 |
FCP | 首次有内容绘制 | 页面首次绘制出任何文本、图像或其他可视元素的时间点,用户可以看到页面有一些可见的内容。 |
LCP | 最大内容绘制 | 页面中「最大的可见内容元素」绘制完成并可见的时间点,通常是页面上最显眼的图像或文本块。 |
TTI | 可交互时间 | 页面加载完成且用户可以与页面进行交互的时间点,主线程空闲且页面响应用户输入。 |
TBT | 总阻塞时间 | 页面加载过程中,主线程被长时间任务(通常是 JavaScript 执行)阻塞的总时间。 |
CLS | 累计布局偏移 | 页面加载过程中发生的意外布局变化的总量,可能导致用户在交互时误触或出现不良体验。 |
FID | 首次输入延迟 | 用户首次与页面交互(如点击按钮)时,页面响应用户输入所需的时间。 |
下文中,如果出现相关术语,我们就不做过多的解释说明了。
❝在
Chrome
的性能指标中,"Contentful"
是一个术语,用来描述页面上已绘制的有意义的内容。 ❞
这里,再啰嗦一遍上面的部分内容。
最大的有意义
的绘制内容。"Contentful"
强调了在页面加载过程中绘制的内容具有意义和可见性,与其他不相关的绘制内容(例如背景或辅助元素)相区分。
对于,渲染阻塞资源/关键渲染路径
的更多介绍,我们之前在浏览器之资源获取优先级(fetchpriority)有过介绍,可以回顾一下。
下文中,出现这些专有名词,我们就不在详细介绍了。
GTmetrix
是一个常用的「网页性能分析工具」,用于评估和优化网站的加载速度和性能。它通过「模拟真实用户访问网页的行为,收集并分析与性能相关的数据,并生成详细的报告和建议」。
GTmetrix
是一个功能强大且易于使用的网页性能工具,它提供了全面的性能分析和优化建议,帮助开发人员优化网站加载速度、提升用户体验,并确保网站在全球范围内的性能表现。
GTmetrix
和我们之前介绍过WebPageTest[1]一样,有异曲同工的作用。
font-display
是一个 CSS 属性,用于控制自定义字体
(如 Web 字体)在加载过程中的显示行为。它允许开发人员在字体加载期间提供更好的用户体验,以避免文本突然闪现或延迟显示的情况。
字体显示时间线基于一个计时器,该计时器在浏览器尝试使用给定下载字体的那一刻开始。时间线分为三个时间段,在这三个时间段中指定使用字体的元素的渲染行为。
时间段 | 渲染行为 |
---|---|
字体阻塞周期 | 如果字体未加载,使用后备字体进行渲染;如果字体加载成功,则正常使用字体。 |
字体交换周期 | 如果字体未加载,使用后备字体进行渲染;如果字体加载成功,则正常使用字体。 |
字体失败周期 | 如果字体未加载,浏览器将其视为加载失败,触发字体回退,使用正常字体替代。 |
以下是对 font-display
属性的不同取值进行介绍的表格:
属性值 | 描述 |
---|---|
auto | 默认值。浏览器根据情况决定如何处理字体显示。 |
block | 在字体加载完成之前,使用占位符进行显示,避免文本闪现或导致布局变化。 |
swap | 在字体加载完成之前,「使用与自定义字体相似的系统默认字体进行显示」,保持整体布局的稳定性。 |
fallback | 在字体加载完成之前,使用与自定义字体相似的系统默认字体进行显示,并在加载完成后切换为自定义字体。 |
optional | 优先显示系统默认字体,在自定义字体在加载期间可用时切换为自定义字体。 |
@font-face {
font-family: 'MyFont';
src: url('myfont.woff2') format('woff2');
font-display: swap;
}
通过设置 font-display
属性,开发人员可以根据实际需求来平衡字体加载速度和页面显示的稳定性。根据具体情况选择合适的值可以提供更好的用户体验,避免突兀的文本显示变化。需要注意的是,字体的加载速度和可用性也受到网络环境和服务器配置等因素的影响。
Chrome DevTools
中的"Coverage"
选项卡可以帮助我们找到「未使用的JavaScript和CSS代码」。删除未使用的代码可以加快页面加载速度,并节省移动用户的流量。
"coverage"
,选择"Show Coverage"
命令,然后按Enter键
执行该命令。Coverage
选项卡将被打开。在Coverage选项卡中,点击以下按钮之一:
❝这是
chrome devtool
文档中的内容,和最新版本的chrome
有所出入,但是主要核心点没变。 ❞
在Coverage选项卡中的表格显示了哪些资源被分析以及每个资源中使用的代码量。点击某一行,可以在Sources面板中打开该资源,并查看逐行分解的已使用代码和未使用代码。任何未使用的代码行开头都会有一条红线。
❝性能分数是基于指标分数的「加权平均值」。 ❞
我们可以看到在Lighthouse
(开源的自动化工具,用于评估网页性能和质量。)中针对FCP/LCP/SI
等的权重。
同时,我们可以通过 Lighthouse Scoring Calculator[3](一个工具,用于计算 Lighthouse
分数)进行模拟计算。
网站的首次内容绘制
(First Contentful Paint
简称:FCP
)是Google核心Web要素中最有意义的指标之一。与其他绘制和加载指标不同,FCP
不是一个纯粹的技术指标,而是「关注用户的体验和他们在网站上首先感知到的内容,而不是后台加载的内容」。通过优化网站的FCP
,你不仅可以加快整体加载时间并提高页面速度评级,还可以向访问者明确显示他们的请求正在被处理,加载没有停滞。
❝网站的
FCP
是指浏览器呈现DOM中的第一个内容片段,向用户提供页面正在加载的第一次反馈 ❞
"Contentful"
包括图像
、canvas
元素(非白色)或文本。简单来说,「FCP就是用户可以看到页面的某个部分发生变化的时刻」。通常,这表现为页眉栏
或背景图片
。这个元素可能不是从服务器渲染或加载的第一个元素,但它是用户可以看到的「第一个元素」,对于网站的用户体验
至关重要。
FCP
不计算包含在iframe
中的内容。非内容绘制,例如「背景颜色」的变化,也不属于FCP
,而是属于FP
(首次绘制)。
FCP
是一个相对主观的测量点。虽然可以定量地测量它,但它也相对主观
。拥有快速的FCP
对于用户来说很重要,因为它会让用户感觉到你的网站加载速度很快,无论实际上是不是如此。与竞争对手相比,你的网站可能具有更长的FID
(首次输入延迟),但由于更快的FCP,它在用户眼中可能会显得更快。
尽管如此,FCP
并不是虚头巴脑的测量指标。
❝较低的FCP时间通常是页面速度的一个良好指标,并且优化它的方法也会影响其他页面速度指标(如
LCP
时间)。 ❞
下图是使用GTmetrix[4]对baidu
的网站的性能分析。
尽管FCP由于用户感知而重要,但它是一种可量化的指标,可以进行测量和评分。
我们可以使用一些工具对网站进行性能分析。而根据测试环境不同,又分为两类:
在深入了解用于检查FCP的各种工具之前,我们需要知道什么是一个良好的FCP得分。根据Google关于确定指标得分的文档[5],我们可以看到他们将FCP时间分为三个类别:
类别 | 时间范围 |
---|---|
良好 (Good) | 0秒至1.8秒 |
需要改进 (Needs Improvement) | 1.8秒至3秒 |
较差 (Poor) | 超过3秒 |
以上表格显示了FCP
时间按照良好
、需要改进
和较差
三个类别进行划分的时间范围。
「工欲善其事,必先利其器」,下面我们就安装环境的不同,列举几个比较常用的工具。大家,业务中有匹配的,可以择优选择。
这些工具又被称为Field tools
。它们是你可以用来跟踪页面在用户眼中的显示情况的工具。这些工具「不依赖于网站的API」。
它们直接针对你的服务器实时运行,以便你尽可能获得最准确和最新的信息。
在介绍FCP
的Google文档[6]中列举了几个比较好用的Field 工具[7]:
这些工具又被称为Lab tools
,它们用于检查FCP的目的是「模拟在理想情况下的FCP结果」。与发生延迟、带宽、网络拥塞和其他阻碍的真实情况不同,Google推荐的这些Lab工具可以展示在最佳运行情况下我们的网站可能达到的状态。
此外,当正在开发尚未投入生产的网站时,无法在真实世界条件下进行测试。使用实验室工具还可以帮助我们在项目在开发周期中逐步推进时创建基准和里程碑。
上述工具可以为我们提供网站速度
和FCP得分的概述和评分。但是它们(以及其他工具如GTmetrix
)还可以为我们提供优化FCP得分并使其更快绘制的建议。
这可能是降低FCP
时间的最重要的页面因素之一。渲染阻塞资源
是网站上必须加载的文件,包括HTML
、JavaScript
、字体
和CSS文件
。它们被称为“渲染阻塞”
,是因为它们优先于页面上的其他内容,会阻止其他内容的加载,直到它们完成加载或执行。
❝任何图像、纯文本或其他面向用户的内容都会被暂停加载,直到这些关键文件完成加载。 ❞
这种暂停加载导致FCP
显著增加,原因有两点:
较大的文件大小
。通过从关键渲染路径
中移除这些资源,可以为内容的绘制腾出空间。我们可以「延迟加载」这些资源,避免使用@import
加载CSS(而是使用@media
加载条件性CSS),确保对CSS
、HTML
和JavaScript
文件进行压缩和合并(关于资源压缩,我们后面会讲到)。
在某些情况下,当网站的其他内容(如图像、样式和脚本)已经加载完成时,页面上的所有文本会突然一下子全部显示出来。这种情况通常发生在「字体加载较慢或延迟的情况」下。
当网站使用自定义字体
(如Web字体)时,浏览器需要下载并加载字体文件,然后再将其应用于页面上的文本元素。如果字体加载过程较慢,浏览器会「先显示默认字体,然后在字体加载完成后再切换为自定义字体」。这种切换可能会导致页面上的文本突然全部显示出来,给用户一种突兀的感觉。
那是因为浏览器将其隐藏起来了。网站的文本内容在准备好可阅读时才加载。文本通常只占用几个字节的内容。但在许多网站上,它的加载时间
可能会呈指数级增长。这是因为「字体文件还没有准备好用于显示。在所有能够实现极快的FCP时间的方法中,使网站的文本内容显示出来可能是最好的方式」。
我们可以使用不同的font-display
参数,告诉浏览器立即使用系统字体加载我们网站的文本内容,然后在加载完成后将其替换为我们指定的显示字体。
文本内容的文件大小很小,通常只有几个字节,通过告诉浏览器立即显示文本内容,可以使我们的FCP几乎不存在。只需在我们的指定@font-face
的 CSS中添加font-display:swap
即可。
❝压缩是指从网站的HTML、CSS和JavaScript文件中删除冗余字符(如空格)。 ❞
虽然空格使人类更容易阅读和解析,但浏览器和服务器并不需要它们。这些空格仍然是占用字节的字符。通过压缩诸如CSS文件之类的内容,您可以减小页面大小,从而提高页面速度并改善FCP时间。
由于,现在网页的组织形式以SPA
居多,那就绕不开构建工具,所以我们简单的列出webpack/vite
如何压缩html/css/js
。这里不做深究。
资源类型 | Webpack 4 | Webpack 5 | Vite |
---|---|---|---|
HTML | HtmlWebpackPlugin | HtmlWebpackPlugin | vite-plugin-html |
文档链接[15] | 文档链接[16] | 文档链接[17] | |
CSS | MiniCssExtractPlugin | CssMinimizerWebpackPlugin | build.cssMinify (使用 esbuild 进行压缩) |
文档链接[18] | 文档链接[19] | 文档链接[20] | |
JS | UglifyjsWebpackPlugin | TerserWebpackPlugin | build.minify (默认使用 Esbuild,可配置 Terser) |
文档链接[21] | 文档链接[22] | 文档链接[23] |
上面的各种插件,只是一个举例,可能不全或者有更好的方式。这里不做更多的分析和说明。
在利用构建工具,将分散四处的资源打包到一起,一定程度下,减少了代码组织的问题,但是又出现了另外一个比较棘手的问题。在页面加载中,有时候加载的资源「远远多于」,我们想要的。
尤其,像CSS/JS
这种渲染阻塞资源
,同时它的加载优先级又很高。在页面渲染中,无疑会增加渲染时间。
所以,我们应该删除任何旧的或未使用的代码,以使其在每次请求您的网站时不被加载。Chrome DevTools[24]可以在“Coverage”
选项卡下显示我们的CSS中正在加载但未使用的部分。
❝TTFB(Time To First Byte)是指从发起网络请求到接收到第一个字节的时间。 ❞
它是衡量网络性能的重要指标之一,特别是对于网页加载速度的评估。TTFB反映了与服务器建立连接、发送请求、服务器处理请求并返回响应的时间。
TTFB包括了多个步骤的时间消耗,例如 DNS解析时间
、建立连接时间
、发送请求时间
以及服务器处理时间
。这些步骤的延迟可能受到网络延迟
、服务器响应速度
、服务器负载
等因素的影响。
较短的TTFB意味着与服务器的通信速度较快,用户能够更快地接收到页面的首个字节,并且网页加载速度可能更快。FCP依赖于这个指标,因此它的速度越快,FCP
就越快。相反,较长的TTFB可能导致用户等待时间增加,网页加载速度变慢。
要减少TTFB可以采取以下方式:
优化方式 | 描述 |
---|---|
优化服务器性能 | 确保服务器硬件和软件的配置足够强大和优化。包括使用高性能的服务器和数据库,以及优化服务器的网络和存储设置。 |
减少网络延迟 | 选择可靠的网络服务提供商,并确保服务器和用户之间的网络连接快速稳定。使用CDN(内容分发网络)可以将内容缓存到离用户更近的服务器上,减少网络传输时间。 |
启用缓存 | 使用适当的缓存策略,将静态资源(如图片、CSS和JavaScript文件)缓存在用户的浏览器或CDN中。这样可以避免重复请求,并加快页面加载速度。 |
优化数据库查询 | 如果网站或应用程序使用数据库,确保数据库查询和操作是高效的。使用索引、优化查询语句和避免不必要的数据库操作可以减少服务器响应时间。 |
压缩传输的数据 | 使用压缩算法(如Gzip)对服务器返回的数据进行压缩,减小传输的数据量,从而加快数据传输速度。 |
异步加载和延迟加载 | 将页面上的某些组件、脚本或资源延迟加载,只在需要时再加载。这样可以提高页面的初始加载速度,减少对服务器的并发请求。 |
❝通过上述处理,
TTFB
少了,进而FCP
也少了。 ❞
这可能是一个很简单的问题。但是,拥有过大的DOM往往是导致快速FCP
的最大限制因素之一。我们总是试图一劳永逸
完成过多的工作。
❝谷歌文档[25]表示,“页面中DOM树深度<32个元素,每个父元素的子元素少于60个是最理想的页面组织结构”。 ❞
许多人为了给访问者留下深刻印象而过分复杂化他们的首页。然而,这些额外的元素会膨胀DOM并导致更长的FCP时间。
我们可以通过「减少使用的CSS选择器的数量」来解决这个问题,尽可能更多地使用基于类的CSS而不是ID或特殊的媒体查询。伪选择器也会复杂化问题并增加DOM的大小。
此外,可以减少选择器应用于的元素数量。加载和应用样式到5个元素比加载和应用样式到10个元素需要更少的时间。
这一点可能不会影响每个网站,这也是为什么我们将它放在列表的最后。图像通常不是首先绘制在页面上的内容,但是将比较重要或者醒目的图像进行格式替换(例如网站的logo)可能有助于改善FCP。
虽然.gif
、.jpg
和.png
是常用的图像文件格式,但如果将它们替换为.webp
或.svg
文件,将节省大量时间。由于文件大小通常只有几个字节而不是几千字节,我们的图像将会在瞬间加载。
作为直接衡量网站性能的指标,FCP的作用并不大。FCP是一个「以用户为中心的感知指标,并不一定能反映网站性能」。正如我们在文章前面提到的,两个网站可能具有相同的加载时间,但FCP时间较短的网站可能被认为加载更快。这种感知可能会影响用户体验,但并不一定反映整体网站性能。
然而,FCP
是一个非常好的指标,可以提高整体网站性能水平。我们采取的任何降低FCP的措施也将降低整体页面速度。因此,几乎可以「将其视为整体性能的信号」。
虽然这两个术语有时可能被交替使用,但从技术上讲,它们是两个不同的指标。正如我们讨论过的,FCP
是指浏览器在页面上呈现第一个DOM元素的时刻。我们可以将其理解为页面上的任何可用(即使不能交互)内容,例如背景图,文本或页眉菜单区域。
而首次绘制
(First Paint)是指浏览器呈现的「第一个字节的信息,无论它是否具有内容」。例如,「背景颜色」的更改(而不是背景图像的加载)并不具有内容。用户无法将其作为内容进行消费。
❝
FP
可能与FCP
完全相同,也可能完全不同。❞
「分享是一种态度」。
参考资料:
[1]
WebPageTest: https://www.webpagetest.org
[2]
打开命令菜单: https://developer.chrome.com/docs/devtools/command-menu/
[3]
Lighthouse Scoring Calculator: https://googlechrome.github.io/lighthouse/scorecalc/#FCP=2568&SI=5800&FMP=4000&TTI=7300&FCI=6500&LCP=4000&TBT=600&CLS=0.25&device=desktop&version=10
[4]
GTmetrix: https://gtmetrix.com/
[5]
指标得分的文档: https://developer.chrome.com/docs/lighthouse/performance/performance-scoring/#metric-scores
[6]
Google文档: https://web.dev
[7]
好用的Field 工具: https://web.dev/user-centric-performance-metrics/#in-the-field
[8]
PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/
[9]
Chrome User Experience Report: https://developers.google.com/web/tools/chrome-user-experience-report
[10]
Search Console (Speed Report): https://webmasters.googleblog.com/2019/11/search-console-speed-report.html
[11]
Web Vitals JavaScript library: https://github.com/GoogleChrome/web-vitals
[12]
Lighthouse: https://developers.google.com/web/tools/lighthouse/
[13]
Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools/
[14]
PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/
[15]
文档链接: https://v4.webpack.js.org/plugins/html-webpack-plugin/
[16]
文档链接: https://webpack.js.org/plugins/html-minimizer-webpack-plugin/
[17]
文档链接: https://github.com/vbenjs/vite-plugin-html/blob/main/README.zh_CN.md
[18]
文档链接: https://v4.webpack.js.org/plugins/mini-css-extract-plugin/
[19]
文档链接: https://webpack.js.org/plugins/css-minimizer-webpack-plugin/
[20]
文档链接: https://cn.vitejs.dev/config/build-options.html#build-minify
[21]
文档链接: https://v4.webpack.js.org/plugins/uglifyjs-webpack-plugin/
[22]
文档链接: https://v4.webpack.js.org/plugins/terser-webpack-plugin/
[23]
文档链接: https://cn.vitejs.dev/config/build-options.html#build-minify
[24]
Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools/
[25]
谷歌文档: https://developer.chrome.com/docs/lighthouse/performance/dom-size/
[26]
FCP: https://web.dev/fcp/
[27]
font-display: https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face/font-display
[28]
GTmetrix: https://gtmetrix.com/
[29]
Coverage: https://developer.chrome.com/docs/devtools/coverage/
[30]
fcp-first-contentful-paint: https://www.elegantthemes.com/blog/wordpress/fcp-first-contentful-paint