优化 Largest Contentful Paint

有关如何细分 LCP 并确定需要改进的关键领域的分步指南。

发布日期:2020 年 4 月 30 日;上次更新日期:2025 年 3 月 31 日

Largest Contentful Paint (LCP) 是三项 Core Web Vitals 指标之一,用于衡量网页主要内容的加载速度。具体来说,LCP 衡量的是从用户开始加载网页到视口内渲染最大图片或文本块的时间。

为了提供良好的用户体验,网站应力求将至少 75% 的网页访问的 LCP 控制在 2.5 秒或更短的时间内。

良好的 LCP 值为 2.5 秒或更短,较差的值为 4.0 秒或更长,介于两者之间的值需要改进
良好的 LCP 值是不超过 2.5 秒。

许多因素都会影响浏览器加载和呈现网页的速度,其中任何一个因素出现延迟都可能会对 LCP 产生重大影响。

很少有针对网页的某个部分进行快速修复就能显著缩短 LCP 用时的情况。为了改善 LCP,您必须查看整个加载过程,并确保沿途的每个步骤都经过优化。

了解 LCP 指标

在优化 LCP 之前,开发者应先了解自己是否存在 LCP 问题,以及问题的严重程度。

许多工具都可以衡量 LCP,但并非所有工具都以相同的方式衡量 LCP。若要了解真实用户的 LCP,我们应查看真实用户的体验,而不是 Lighthouse 等基于实验室的工具或本地测试显示的结果。这些基于实验室的工具可以提供丰富的信息来解释并帮助您改进 LCP,但请注意,仅靠实验室测试可能无法完全代表实际用户的体验。

基于真实用户的 LCP 数据可以通过安装在网站上的实时用户监控 (RUM) 工具获取,也可以通过 Chrome 用户体验报告 (CrUX) 获取,后者会从数百万个网站的真实 Chrome 用户那里收集匿名数据。

使用 Chrome 开发者工具 CrUX LCP 数据

Chrome 开发者工具的“性能”面板会在实时指标视图中显示网页或来源的 CrUX LCP 旁边的本地 LCP 体验,并在包含 LCP 子部分时间细分的性能轨迹的分析中显示本地 LCP 体验(我们稍后会对此进行说明)。

Chrome 开发者工具的“性能”面板中的本地 LCP 和实测 LCP
Chrome 开发者工具“性能”面板中的本地 LCP 和实际 LCP(实时指标和轨迹视图)。

通过将现场数据叠加到“性能”面板上,您可以评估网页是否存在任何真实用户 LCP 问题,并调整本地环境设置,以便更好地重现和调试这些问题。

使用 PageSpeed Insights CrUX LCP 数据

PageSpeed Insights 在标记为了解真实用户的体验的顶部部分中提供对 CrUX 数据的访问权限。如需查看更详细的实验室数据,请参阅标记为诊断性能问题的底部部分。如果您的网站有 CrUX 数据,请务必先重点关注真实用户数据。

PageSpeed Insights 中显示的 CrUX 数据
PageSpeed Insights 中显示的 CrUX 数据。

PageSpeed Insights 最多会显示四种不同的 CrUX 数据:

  • 相应网址移动版数据
  • 此网址桌面版数据
  • 整个来源移动数据
  • 整个来源桌面设备数据

您可以在此部分顶部和右上角的控件中切换这些设置。如果某个网址的数据不足以在网址级层显示,但有源级层的数据,PageSpeed Insights 始终会显示源级层的数据。

PageSpeed Insights 在没有网址级数据时回退到源级数据
如果 PageSpeed Insights 没有网址级数据,则会显示来源级数据。

整个来源的 LCP 可能与单个网页的 LCP 大相径庭,具体取决于相应网页上的 LCP 加载方式与该来源中其他网页的 LCP 加载方式相比如何。此外,访问者浏览这些页面的方式也会影响此指标。首页往往是新用户访问的页面,因此可能经常在没有任何缓存内容的情况下“冷”加载,因此往往是网站上加载速度最慢的页面。

查看四种不同类别的 CrUX 数据有助于您了解 LCP 问题是特定于此网页,还是更普遍的网站级问题。同样,它还可以显示哪些设备类型存在 LCP 问题。

使用 PageSpeed Insights CrUX 补充指标

如果想优化 LCP,还应使用首次内容渲染 (FCP)首字节到达时间 (TTFB) 这两个时间指标,它们是良好的诊断指标,可为 LCP 提供有价值的分析洞见。

TTFB 是指从访问者开始导航到某个网页(例如点击链接)到收到 HTML 文档的第一个字节之间的时间。较高的 TTFB 可能会使 LCP 达到 2.5 秒的目标变得困难,甚至不可能。

TTFB 较高可能是因为服务器重定向次数过多、访问者距离最近的网站服务器较远、访问者网络状况不佳,或者由于查询参数而无法使用缓存的内容。

网页开始渲染后,可能会先进行初始绘制(例如,背景颜色),然后显示一些内容(例如,网站标题)。初始内容的显示时间由 FCP 衡量。FCP 与其他指标之间的差值非常能说明问题。

TTFB 与 FCP 之间的差值较大可能表明浏览器需要下载大量会阻止渲染的资源。这也可能表明,该网站必须完成大量工作才能呈现任何有意义的内容,这是严重依赖客户端渲染的网站的典型特征。

FCP 与 LCP 之间的差值较大,表明 LCP 资源要么无法立即供浏览器优先处理(例如,由 JavaScript 管理的文本或图片,而不是在初始 HTML 中提供的文本或图片),要么浏览器在显示 LCP 内容之前正在完成其他工作。

使用 PageSpeed Insights Lighthouse 数据

PageSpeed Insights 的 Lighthouse 部分提供了一些有关如何改进 LCP 的指南,但您应先检查给出的 LCP 是否与 CrUX 提供的真实用户数据大致一致。如果 Lighthouse 和 CrUX 的结果不一致,那么 CrUX 可能更准确地反映了您的用户体验。在根据 CrUX 数据采取行动之前,请确保这些数据是针对您的网页,而不是整个来源。

如果 Lighthouse 和 CrUX 都显示 LCP 值需要改进,Lighthouse 部分可以提供有关如何改进 LCP 的宝贵指导。使用 LCP 过滤条件可仅显示与 LCP 相关的审核,如下所示:

Lighthouse LCP 优化和诊断
Lighthouse 诊断和有关如何改进 LCP 的建议。

除了可用于改进的机会之外,还有诊断信息,可提供更多信息来帮助诊断问题。“最大内容渲染时间元素”诊断信息会显示构成 LCP 的各种时间点的实用细分数据:

Lighthouse 中的 LCP 子部分
Lighthouse 对 LCP 元素的细分。

LCP 资源类型和子部分也可在 CrUX 中使用

接下来,我们将深入探讨这些子部分。

LCP 细分

如果 PageSpeed Insights 未提供有关如何改进 LCP 指标的答案,那么优化 LCP 可能是一项更复杂的任务。对于复杂任务,最好将其分解为更小、更易于管理的任务,然后分别处理每个任务。

本部分介绍了一种方法,用于将 LCP 分解为最关键的子部分,然后针对如何优化每个部分提供具体建议和最佳实践。

大多数网页加载通常包含许多网络请求,但为了确定可缩短 LCP 的机会,您应先仅查看以下两项:

  1. 初始 HTML 文档
  2. LCP 资源(如果适用)

虽然网页上的其他请求也会影响 LCP,但这两个请求(尤其是 LCP 资源开始和结束的时间)可以揭示您的网页是否针对 LCP 进行了优化。

如需确定 LCP 资源,您可以使用开发者工具(例如前面讨论的 PageSpeed Insights、Chrome 开发者工具WebPageTest)来确定 LCP 元素。然后,您可以在网页加载的所有资源的网络瀑布图中,将元素加载的网址(如果适用,则再次)进行匹配。

例如,以下可视化图表显示了典型网页加载的网络瀑布图,其中突出显示了这些资源,LCP 元素需要图片请求才能呈现。

突出显示了 HTML 和 LCP 资源的瀑布图
瀑布图,显示了网页的 HTML 和 LCP 所需资源的加载时间。

对于经过良好优化的网页,您希望 LCP 资源请求尽早开始加载,并希望 LCP 元素在 LCP 资源完成加载后尽快渲染。为了直观地了解特定网页是否遵循此原则,您可以将 LCP 总时间分解为以下子部分:

第一字节时间 (TTFB)
从用户开始加载网页到浏览器收到 HTML 文档响应的第一个字节所用的时间。
资源加载延迟
TTFB 与浏览器开始加载 LCP 资源之间的时间。如果 LCP 元素不需要加载资源即可呈现(例如,如果该元素是使用系统字体呈现的文本节点),则此时间为 0。
资源加载时长
加载 LCP 资源本身所需的时间。如果 LCP 元素不需要加载资源即可呈现,则此时间为 0。
元素渲染延迟
从 LCP 资源完成加载到 LCP 元素完全渲染之间的时间。

每个网页的 LCP 都包含以下四个子类别。它们之间没有间隙或重叠,并且加起来等于完整的 LCP 时间。

LCP 的细分,显示了四个子类别
同一瀑布图,时间轴上叠加了四个 LCP 子类别。

每个网页的 LCP 值都可以分解为这四个子部分。它们之间没有重叠或间隙。这些时间加起来就是完整的 LCP 时间。

在优化 LCP 时,尝试单独优化这些子部分会很有帮助。但请务必注意,您需要优化所有这些广告。在某些情况下,应用于某个部分的优化不会改善 LCP,只会将节省的时间转移到另一部分。

例如,在之前的网络瀑布图中,如果您通过压缩图片或改用更优的格式(例如 AVIF 或 WebP)来减小图片的文件大小,则会缩短资源加载时长,但实际上不会改善 LCP,因为时间只会转移到元素渲染延迟子部分:

与之前显示的 LCP 细分相同,其中资源加载时长子类别缩短,但总体 LCP 时间保持不变。
缩短资源加载时长会增加元素渲染延迟,但不会缩短 LCP。

之所以会发生这种情况,是因为在此网页上,LCP 元素在 JavaScript 代码完成加载之前处于隐藏状态,然后所有内容会一次性显示出来。

此示例有助于说明,您需要优化所有这些子部分,才能获得最佳 LCP 结果。

最佳子部分时间

为了优化 LCP 的每个子部分,务必要了解优化良好的网页上这些子部分的理想细分情况。

在四个子部分中,有两个的名称中包含“delay”一词。这表明您希望这些时间尽可能接近于零。另外两部分涉及网络请求,而网络请求本身就需要时间。

LCP 子部分 LCP 占比 (%)
加载第一个字节所需时间 ~40%
资源加载延迟 <10%
资源加载时长 ~40%
元素渲染延迟 <10%
总计 100%

请注意,这些时间细分可作为一般性的指导,而非硬性规定。如果网页上的 LCP 时间始终在 2.5 秒内,那么相对比例是多少并不重要。但如果您在任一“延迟”部分花费了大量不必要的时间,那么将很难始终达到 2.5 秒的目标

一种不错的 LCP 时间细分思路是:

  • 绝大部分 LCP 时间应该花在加载 HTML 文档和 LCP 源上。
  • 在 LCP 之前的任何时间,如果这两个资源中的一个加载,则有机会进行改进

如何优化每个部分

现在,您已经了解了在经过良好优化的网页上,每个 LCP 子部分的时间应如何分解,接下来就可以开始优化自己的网页了。

接下来的四个部分将介绍有关如何优化每个部分的建议和最佳实践。这些建议会按顺序显示,首先显示可能带来最大效果的优化建议。

1. 消除资源加载延迟

此步骤的目标是确保 LCP 资源尽早开始加载。虽然从理论上讲,资源最早可以在 TTFB 之后立即开始加载,但在实践中,浏览器在实际开始加载资源之前总是会存在一些延迟。

一个不错的经验法则是,LCP 资源应与该网页加载的第一个资源同时开始加载。换句话说,如果 LCP 资源开始加载的时间晚于第一个资源,则有改进空间。

一个网络瀑布流图,显示了 LCP 资源在第一个资源之后开始,表明有改进空间
在此网页上,LCP 资源在首先加载的样式表之后才开始加载。这方面还有提升空间。

一般来说,有两个因素会影响 LCP 资源的加载速度:

  • 发现资源的时间。
  • 资源获得的优先级。

在发现资源时进行优化

为确保 LCP 资源尽早开始加载,关键在于浏览器预加载扫描器能够在初始 HTML 文档响应中发现该资源。例如,在以下情况下,浏览器可以通过扫描 HTML 文档响应来发现 LCP 资源:

  • LCP 元素是 <img> 元素,并且其 srcsrcset 属性存在于初始 HTML 标记中。
  • LCP 元素需要 CSS 背景图片,但该图片是使用 HTML 标记中的 <link rel="preload">(或使用 Link 标头)预加载的。
  • LCP 元素是需要使用 Web 字体进行渲染的文本节点,并且该字体是使用 HTML 标记中的 <link rel="preload">(或使用 Link 标头)加载的。

以下是一些无法通过扫描 HTML 文档响应来发现 LCP 资源的情况:

  • LCP 元素是使用 JavaScript 动态添加到网页中的 <img>
  • LCP 元素通过 JavaScript 库延迟加载,该库会隐藏其 srcsrcset 属性(通常为 data-srcdata-srcset)。
  • LCP 元素需要 CSS 背景图片。

在上述每种情况下,浏览器都需要先运行脚本或应用样式表(通常需要等待网络请求完成),然后才能发现 LCP 资源并开始加载。这绝不是最佳做法。

为消除不必要的资源加载延迟,您的 LCP 资源应可从 HTML 源代码中发现。如果资源仅从外部 CSS 或 JavaScript 文件中引用,则应使用较高的提取优先级预加载 LCP 资源,例如:

<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/to/styles.css">

<!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">

优化资源获得的优先级

即使 LCP 资源可从 HTML 标记中发现,它仍然可能不会像第一个资源那样尽早开始加载。如果浏览器预加载扫描器的优先级启发法无法识别出相应资源的重要性,或者如果它确定其他资源更重要,则可能会发生这种情况。

例如,如果您在 <img> 元素上设置 loading="lazy",则可以使用 HTML 延迟 LCP 图片。使用延迟加载意味着,在布局确认图片位于视口中之前,资源不会加载,因此加载时间可能会比正常情况下晚。

即使没有延迟加载,浏览器也不会以最高优先级初始加载图片,因为它们不是会阻止渲染的资源。对于可以从更高优先级中受益的资源,您可以使用 fetchpriority 属性向浏览器提示哪些资源最重要:

<img fetchpriority="high" src="/path/to/hero-image.webp">

如果您认为某个 <img> 元素很可能是网页的 LCP 元素,最好为该元素设置 fetchpriority="high"。不过,如果将多个图片(超过一两个)设置为高优先级,则优先级设置对缩短 LCP 毫无帮助。

您还可以降低文档响应中可能位于较早位置但因样式设置而不可见的图片的优先级,例如启动时不可见的轮播幻灯片中的图片:

<img fetchpriority="low" src="/path/to/carousel-slide-3.webp">

对某些资源进行降级可以为更需要带宽的资源提供更多带宽,但请务必谨慎操作。请务必在开发者工具中检查资源优先级,并使用实验室和现场工具测试更改。

优化 LCP 资源优先级和发现时间后,您的网络瀑布图应如下所示(LCP 资源与第一个资源同时开始):

一个网络瀑布图,显示 LCP 资源现在与第一个资源同时开始
LCP 资源现在与样式表同时开始加载。

2. 消除元素渲染延迟

此步骤的目标是确保 LCP 元素可在其资源完成加载(无论何时)后立即渲染。

LCP 元素无法在其资源完成加载后立即渲染的主要原因是,渲染因其他原因而被阻止

  • 由于 <head> 中仍在加载的样式表或同步脚本,整个网页的渲染被阻塞。
  • LCP 资源已完成加载,但 LCP 元素尚未添加到 DOM 中(它正在等待某些 JavaScript 代码加载)。
  • 该元素正被其他代码隐藏,例如仍在确定用户应加入哪个实验的 A/B 测试库。
  • 主线程因长时间运行的任务而处于阻塞状态,渲染工作需要等到这些长时间运行的任务完成后才能进行。

以下部分介绍了如何解决不必要的元素渲染延迟的最常见原因。

减少或内嵌阻塞渲染的样式表

从 HTML 标记加载的样式表会阻止渲染其后的所有内容,这很好,因为您通常不希望渲染未设置样式的 HTML。不过,如果样式表过大,导致其加载时间明显长于 LCP 资源,那么即使 LCP 资源已完成加载,样式表也会阻止 LCP 元素渲染,如本例所示:

网络瀑布图,显示了一个大型 CSS 文件因加载时间长于 LCP 资源而阻止了 LCP 元素的渲染
图片和样式表同时开始加载,但图片在样式表准备就绪之前无法呈现。

如需解决此问题,您可以采取以下任一方案:

  • 将样式表内嵌到 HTML 中,以避免额外的网络请求;或者
  • 减小样式表的大小。

一般来说,只有当样式表较小时,才建议内嵌样式表,因为 HTML 中的内嵌内容无法在后续网页加载中受益于缓存。如果样式表过大,导致加载时间比 LCP 资源长,则不太适合内嵌。

在大多数情况下,确保样式表不会阻塞 LCP 元素渲染的最佳方式是减小其大小,使其小于 LCP 资源。这应可确保它不会成为大多数访问的瓶颈。

以下是一些有助于缩减样式表大小的建议:

延后或内嵌会阻止渲染的 JavaScript

几乎从不需要向网页的 <head> 中添加同步脚本(不含 asyncdefer 属性的脚本),这样做几乎总是会对性能产生负面影响。

如果 JavaScript 代码需要在网页加载时尽早运行,最好将其内嵌,这样渲染就不会因等待其他网络请求而延迟。不过,与样式表一样,只有当脚本非常小时,您才应将其内嵌。

错误做法
<head>
  <script src="/path/to/main.js"></script>
</head>
正确做法
<head>
  <script>
    // Inline script contents directly in the HTML.
    // IMPORTANT: only do this for very small scripts.
  </script>
</head>

使用服务器端渲染

服务器端呈现 (SSR) 是指在服务器上运行客户端应用逻辑,并使用完整的 HTML 标记来响应 HTML 文档请求的过程。

从优化 LCP 的角度来看,SSR 有两个主要优势:

  • 您的图片资源将可从 HTML 源代码中发现(如上文第 1 步中所述)。
  • 您的网页内容无需额外的 JavaScript 请求即可完成渲染。

SSR 的主要缺点是需要额外的服务器处理时间,这可能会减慢 TTFB。不过,这种权衡通常是值得的,因为服务器处理时间在您的控制范围内,而用户的网络和设备功能不在您的控制范围内。

与 SSR 类似的选项称为静态网站生成 (SSG) 或预呈现。这是在构建步骤中(而不是按需)生成 HTML 页面的过程。如果您的架构支持预渲染,那么从性能角度来看,预渲染通常是更好的选择。

拆分长任务

即使您已遵循之前的建议,并且您的 JavaScript 代码不会阻塞渲染,也不会负责渲染元素,但它仍可能会延迟 LCP。

出现这种情况的最常见原因是网页加载了大型 JavaScript 文件,这些文件需要在浏览器的主线程上进行解析和执行。这意味着,即使图片资源已完全下载,也可能仍需等待不相关的脚本执行完毕后才能进行渲染。

目前,所有浏览器都在主线程上渲染图片,这意味着任何会阻塞主线程的操作都可能导致不必要的元素渲染延迟

3. 缩短资源加载时长

此步骤的目标是减少通过网络将资源字节传输到用户设备所花费的时间。一般来说,您可以通过以下四种方式来完成此操作:

  • 缩减资源的大小。
  • 缩短资源必须移动的距离。
  • 减少对网络带宽的争用。
  • 完全消除网络时间。

缩减资源的大小

网页的 LCP 资源(如果有)将是图片或 Web 字体。以下指南详细介绍了如何缩减以下两项的大小:

缩短资源必须经过的距离

除了减小资源大小之外,您还可以通过让服务器尽可能靠近用户来缩短加载时间。实现这一目标的最佳方式是使用内容分发网络 (CDN)。

图片 CDN 尤其有用,因为它们不仅可以缩短资源传输距离,还可以减小资源大小,自动为您实现之前的所有大小缩减建议。

减少对网络带宽的争用

即使您已减小资源的大小和传输距离,如果您同时加载许多其他资源,资源仍可能需要很长时间才能加载完毕。此问题称为网络争用

如果您为 LCP 资源指定了较高的 fetchpriority尽早开始加载该资源,那么浏览器会尽最大努力防止低优先级资源与该资源竞争。不过,如果您加载了许多具有较高 fetchpriority 的资源,或者只是加载了大量资源,那么这可能会影响 LCP 资源的加载速度。

完全消除网络时间

缩短资源加载时长的最佳方法是从流程中完全移除网络。如果您使用高效的 cache-control 政策来提供资源,那么第二次请求这些资源的访问者将从缓存中获取这些资源,从而使资源加载时长基本上为零!

如果 LCP 资源是 Web 字体,除了减小 Web 字体大小之外,您还应考虑是否需要在加载 Web 字体资源时阻止渲染。如果您将 font-display 值设置为 autoblock 以外的任何值,则文本将在加载期间始终可见,并且 LCP 不会因额外的网络请求而被阻塞。

最后,如果 LCP 资源较小,则可以考虑将资源内嵌为 data 网址,这样也可以消除额外的网络请求。不过,使用数据网址需要注意一些事项,因为这样一来,资源就无法缓存,并且在某些情况下,由于额外的解码成本,可能会导致渲染延迟时间更长。

4. 缩短加载第一个字节所需时间

此步骤的目标是尽快提供初始 HTML。此步骤之所以列在最后,是因为开发者通常对此步骤的控制权最少。不过,这也是最重要的步骤之一,因为它会直接影响后续的每个步骤。在后端传送第一个内容字节之前,前端不会发生任何事情,因此,您采取的任何加快 TTFB 的措施都会改善其他所有加载指标。

对于原本速度很快的网站,TTFB 较慢的常见原因是访问者通过多次重定向(例如通过广告或缩短的链接)到达网站。始终尽可能减少访问者必须等待的重定向次数。

另一个常见原因是无法从 CDN 边缘服务器使用缓存内容,并且所有请求都必须一直返回到源服务器。如果访问者使用唯一的网址参数进行分析,即使这些参数不会导致网页发生变化,也可能会出现这种情况。

如需有关优化 TTFB 的具体指导,请参阅优化 TTFB 指南

在 JavaScript 中监控 LCP 细分

您可以通过以下性能 API 的组合,在 JavaScript 中获取前面讨论的所有 LCP 子部分的计时信息:

许多 RUM 产品已使用这些 API 计算子部分。web-vitals 库还在归因 build 中包含这些 LCP 子部分计时,您可以参考其代码,了解如何在 JavaScript 中计算这些计时。

Chrome 开发者工具和 Lighthouse 也会测量这些子部分(如之前的屏幕截图所示),因此在使用这些工具时,您无需在 JavaScript 中手动计算它们。

摘要

LCP 非常复杂,其时间可能会受到多种因素的影响。但如果您认为优化 LCP 主要在于优化 LCP 资源的加载,那么事情就会变得简单得多。

概括来讲,优化 LCP 可归纳为四个步骤:

  1. 确保 LCP 资源尽早开始加载。
  2. 确保 LCP 元素可在其资源完成加载后立即渲染。
  3. 在不牺牲质量的情况下,尽可能缩短 LCP 资源的加载时间。
  4. 尽快提供初始 HTML 文档。

如果您能够在网页上遵循这些步骤,那么您应该有信心为用户提供最佳的加载体验,并且您应该会在实际 LCP 得分中看到这一点。