什么是 FCP?
首次内容渲染 (FCP) 用于衡量从用户首次导航到网页到网页任何一部分内容呈现在屏幕上的时间。对于此指标,“内容”是指文本、图片(包括背景图片)、<svg>
元素或非白色 <canvas>
元素。
在上图中所示的加载时间轴中,FCP 发生在第二帧,因为这是第一个文本和图片元素渲染到屏幕上的时间。
您会发现,虽然部分内容已呈现,但并非所有内容都已呈现。这是一个重要的区别,需要在 First Contentful Paint 和 Largest Contentful Paint (LCP) 之间加以区分,后者旨在衡量网页的主要内容何时加载完毕。
FCP 得分多少算好?
为了提供良好的用户体验,网站应尽量将首次有意义的绘制时间控制在 1.8 秒或更短的时间。为确保大多数用户都能达到此目标值,一个合适的衡量阈值是网页加载时间的第 75 个百分位数,并按移动设备和桌面设备进行细分。
如何衡量 FCP
现场工具
实验室工具
在 JavaScript 中衡量 FCP
如需在 JavaScript 中衡量 FCP,您可以使用 Paint Timing API。以下示例展示了如何创建一个 PerformanceObserver
,用于监听名称为 first-contentful-paint
的 paint
条目并将其记录到控制台。
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntriesByName('first-contentful-paint')) {
console.log('FCP candidate:', entry.startTime, entry);
}
}).observe({type: 'paint', buffered: true});
在前面的代码段中,记录的 first-contentful-paint
条目会告知您绘制出第一个有内容的元素的时间。不过,在某些情况下,此条目不适用于衡量 FCP。
以下部分列出了 API 报告的内容与指标计算方式之间的差异。
指标与 API 之间的差异
- API 会为在后台标签页中加载的网页分派
first-contentful-paint
条目,但在计算 FCP 时应忽略这些网页(仅当网页在整个时间都处于前台时,才应考虑首次绘制时间)。 - 当网页从返回/前进缓存恢复时,API 不会报告
first-contentful-paint
条目,但在这些情况下,应衡量 FCP,因为用户会将其视为不同的网页访问。 - 该 API 可能不会报告来自跨源 iframe 的绘制时间,但为了正确衡量 FCP,您应考虑所有帧。子帧可以使用此 API 向父帧报告其绘制时间以进行汇总。
- 该 API 会从导航开始时刻测量 FCP,但对于预渲染网页,应从
activationStart
开始测量 FCP,因为这与用户体验到的 FCP 时间相对应。
开发者无需记住所有这些细微差异,只需使用 web-vitals
JavaScript 库来衡量 FCP,该库会为您处理这些差异(在可能的情况下,请注意不涵盖 iframe 问题):
import {onFCP} from 'web-vitals';
// Measure and log FCP as soon as it's available.
onFCP(console.log);
您可以参阅 onFCP()
的源代码,查看有关如何在 JavaScript 中衡量 FCP 的完整示例。
如何提高 FCP
如需了解如何提高特定网站的 FCP,您可以运行 Lighthouse 性能审核,并留意审核中建议的任何具体优化建议或诊断结果。
如需了解如何普遍提高 FCP(适用于任何网站),请参阅以下效果指南:
- 移除阻塞渲染的资源
- 缩减 CSS 大小
- 移除未使用的 CSS
- 移除未使用的 JavaScript
- 预先连接到必需的源
- 缩短服务器响应时间 (TTFB)
- 避免多次网页重定向
- 预加载密钥请求
- 避免网络载荷过大
- 采用高效的缓存策略提供静态资源
- 避免 DOM 规模过大
- 最大限度地缩短关键请求深度
- 确保文本在网页字体加载期间保持可见状态
- 请保持较低的请求数量和较小的传输大小
更新日志
有时,我们会在用于衡量指标的 API 中发现 bug,有时也会在指标本身的定义中发现 bug。因此,有时必须进行更改,这些更改可能会在内部报告和信息中心中显示为改进或回归。
为帮助您管理这些指标,我们会在此更新日志中显示对这些指标的实现或定义所做的所有更改。
如果您对这些指标有任何反馈,可以通过 web-vitals-feedback Google 群组提供反馈。