什么是 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,但对于预渲染的网页,FCP 应从
activationStart
开始衡量,因为这与用户实际体验到的 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 群组提供反馈。