优化 Largest Contentful Paint

有关如何细分 LCP 并确定需要改进的主要方面的分步指南。

发布时间:2020 年 4 月 30 日

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) 来获取基于真实用户的 LCP 数据,后者会从数百万个网站的真实 Chrome 用户那里收集匿名数据。

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

Chrome DevTools 的“Performance”面板会在实时指标视图中,在网页或来源的 CrUX LCP 旁边显示您的本地 LCP 体验。

Chrome 开发者工具“Performance”面板中的本地 LCP 和现场 LCP
Chrome DevTools 性能面板中的本地 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 的用户还应使用 First Contentful Paint (FCP)Time to First Byte (TTFB) 时间,这两个指标是良好的诊断指标,可提供有关 LCP 的宝贵数据洞见。

TTFB 是指从访问者开始导航到网页(例如点击链接)到收到 HTML 文档的第一个字节所用的时间。TTFB 较高可能会导致实现 2.5 秒的 LCP 变得非常困难,甚至无法实现。

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

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

TTFB 和 FCP 之间存在较大差异可能表示浏览器需要下载大量会阻止呈现的资源。这也可能是网站必须完成大量工作才能呈现任何有意义的内容,这是网站严重依赖客户端呈现的典型迹象。

FCP 和 LCP 之间存在较大差异表示 LCP 资源无法立即供浏览器优先处理(例如,文本或图片由 JavaScript 管理,而不是在初始 HTML 中提供),或者浏览器正在完成其他工作,然后才能显示 LCP 内容。

使用 PageSpeed Insights Lighthouse 数据

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

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

Lighthouse LCP 优化建议和诊断
Lighthouse 诊断和有关如何缩短 LCP 时间的建议。

除了改进建议之外,诊断信息可能还会提供更多信息,帮助您诊断问题。Largest Contentful Paint 元素诊断会显示构成 LCP 的各种时间的详细信息:

Lighthouse 中的 LCP 阶段
Lighthouse 对 LCP 元素的细分。

我们将在下一部分中深入探讨这些子部分。

LCP 细分

如果 PageSpeed Insights 未能为您提供有关如何改进此指标的答案,那么针对 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 的每个子部分,请务必了解经过充分优化的网页上这些子部分的理想细分。

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

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 元素是一种 <img>,使用 JavaScript 动态添加到网页中。
  • LCP 元素会使用会隐藏其 srcsrcset 属性(通常为 data-srcdata-srcset)的 JavaScript 库进行延迟加载。
  • 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">

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

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

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

2. 消除元素渲染延迟

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

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

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

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

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

从 HTML 标记加载的样式表会阻止渲染其后面的所有内容,这很好,因为您通常不希望渲染未设置样式的 HTML。不过,如果样式表太大,其加载时间比 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 资源的加载速度。

完全消除网络时间

缩短资源加载时长的最佳方法是从进程中完全移除网络。如果您使用高效的缓存控制政策提供资源,那么再次请求这些资源的访问者将从缓存中获取这些资源,从而将资源加载时长几乎缩短为零!

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

最后,如果您的 LCP 资源较小,不妨将资源作为数据网址内嵌,这样还可以消除额外的网络请求。不过,使用数据网址需要注意,因为这样就无法缓存资源,在某些情况下,还会因额外的解码开销而导致更长的呈现延迟时间。

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

此步骤的目标是尽快提供初始 HTML。此步骤列在最后,是因为开发者对此步骤的控制力度通常最小。不过,这也是最重要的步骤之一,因为它会直接影响后续的每个步骤。在后端传送第一字节的内容之前,前端无法执行任何操作,因此您可以采取任何措施来缩短 TTFB,这也会改善所有其他加载指标。

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

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

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

在 JavaScript 中监控 LCP 细分

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

在 JavaScript 中计算这些时间值的好处在于,您可以将其发送到分析服务提供商或将其记录到开发者工具,以便进行调试和优化。

例如,以下屏幕截图使用 User Timing API 中的 performance.measure() 方法向 Chrome 开发者工具“性能”面板中的“时间”轨道添加条状图。

Chrome 开发者工具中直观显示的 LCP 子类别的 User Timing 衡量结果
“计时”轨迹显示 LCP 子类别的时间轴。

在查看网络轨道和主线程轨道的同时,查看时间轨道中的可视化结果特别有用,因为您可以一目了然地了解这些时间段内网页上发生的其他情况。

除了在时间轨迹中直观呈现 LCP 子部分之外,您还可以使用 JavaScript 计算每个子部分在总 LCP 时间中的百分比。有了这些信息,您就可以确定自己的网页是否符合前面介绍的建议的百分比细分

此屏幕截图显示了一个示例,该示例会将每个 LCP 子部分的总时间以及其在 LCP 总时间中的百分比记录到控制台。

输出到控制台的 LCP 子类别时间以及相应的 LCP 百分比
LCP 子类别时间和百分比。

这两种可视化图表都是使用以下代码创建的:

const LCP_SUB_PARTS = [
 
'Time to first byte',
 
'Resource load delay',
 
'Resource load duration',
 
'Element render delay',
];

new PerformanceObserver((list) => {
 
const lcpEntry = list.getEntries().at(-1);
 
const navEntry = performance.getEntriesByType('navigation')[0];
 
const lcpResEntry = performance
   
.getEntriesByType('resource')
   
.filter((e) => e.name === lcpEntry.url)[0];

 
// Ignore LCP entries that aren't images to reduce DevTools noise.
 
// Comment this line out if you want to include text entries.
 
if (!lcpEntry.url) return;

 
// Compute the start and end times of each LCP sub-part.
 
// WARNING! If your LCP resource is loaded cross-origin, make sure to add
 
// the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
 
const ttfb = navEntry.responseStart;
 
const lcpRequestStart = Math.max(
    ttfb
,
   
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
    lcpResEntry
? lcpResEntry.requestStart || lcpResEntry.startTime : 0
 
);
 
const lcpResponseEnd = Math.max(
    lcpRequestStart
,
    lcpResEntry
? lcpResEntry.responseEnd : 0
 
);
 
const lcpRenderTime = Math.max(
    lcpResponseEnd
,
   
// Use LCP startTime (the final LCP time) because there are sometimes
   
// slight differences between loadTime/renderTime and startTime
   
// due to rounding precision.
    lcpEntry
? lcpEntry.startTime : 0
 
);

 
// Clear previous measures before making new ones.
 
// Note: due to a bug, this doesn't work in Chrome DevTools.
  LCP_SUB_PARTS
.forEach((part) => performance.clearMeasures(part));

 
// Create measures for each LCP sub-part for easier
 
// visualization in the Chrome DevTools Performance panel.
 
const lcpSubPartMeasures = [
    performance
.measure(LCP_SUB_PARTS[0], {
      start
: 0,
      end
: ttfb,
   
}),
    performance
.measure(LCP_SUB_PARTS[1], {
      start
: ttfb,
      end
: lcpRequestStart,
   
}),
    performance
.measure(LCP_SUB_PARTS[2], {
      start
: lcpRequestStart,
      end
: lcpResponseEnd,
   
}),
    performance
.measure(LCP_SUB_PARTS[3], {
      start
: lcpResponseEnd,
      end
: lcpRenderTime,
   
}),
 
];

 
// Log helpful debug information to the console.
  console
.log('LCP value: ', lcpRenderTime);
  console
.log('LCP element: ', lcpEntry.element, lcpEntry.url);
  console
.table(
    lcpSubPartMeasures
.map((measure) => ({
     
'LCP sub-part': measure.name,
     
'Time (ms)': measure.duration,
     
'% of LCP': `${
       
Math.round((1000 * measure.duration) / lcpRenderTime) / 10
     
}%`,
   
}))
 
);
}).observe({type: 'largest-contentful-paint', buffered: true});

您可以将此代码按原样用于本地调试,也可以对其进行修改以将这些数据发送到分析服务提供商,以便更好地了解真实用户在您的网页上获得的 LCP 细分数据。

摘要

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

概括来讲,优化 LCP 可分为以下四个步骤:

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

如果您能够在自己的网页上按照这些步骤操作,则可以放心地为用户提供最佳加载体验,并且您应该会在实际 LCP 得分中看到这一点。