← 返回 大型网站的核心网络生命体征:如何实现低于1.5秒的LCP -- 线条风格插图

大型网站的核心网页指标:如何达到1.5秒以下的LCP

性能与 Core Web Vitals

早在 2022 年,一个主机对比网站的项目落到了我的案头。大型目录,约 4,000 个页面,类别结构深度嵌套,联盟链接散布其中,英雄图像大得离谱。他们的 Google Search Console 状况糟糕透顶。移动端 LCP 停留在 4.2 秒。INP(当时还叫 FID)勉强达标。客户已经花了 6,000 英镑给前一家代理商,他们只是部署了一个 CDN 然后拍拍屁股走人。

那个项目最终塑造了我们在 Seahawk 对高页面数网站、目录网站、列表平台、HostList 风格的主机评测网站等的性能理解方式。接下来是实际的执行手册。

---

为什么大型网站的LCP问题不同

小型网站有简单的问题。一个英雄图像、一个主题、一个插件做太多事情。修复这三样东西,你就可以在2秒以内了。

大型网站?完全是另一种动物。LCP 元素因页面而异。类别归档页的 LCP 候选元素与产品详情页不同,与首页也不同。大多数性能工具报告单一分数。这个数字是谎言,它是一大堆差异巨大的页面的平均值,只修复首页而忽视底下 3,800 个列表页正是代理商获得恶名的方式。

Google 的 Core Web Vitals 文档很明确:现场数据,即真实用户体验,在 Chrome 用户体验报告中测量,才是 Google 用于排名信号的内容。PageSpeed Insights 的实验室数据只是参考,不是决定性的。我见过网站在 PSI 上得分 95,但 CrUX 数据中 LCP 仍是差评。别搞混了。

列表网站上的三个真实罪魁祸首

在我审计过的每个大型网站上(到目前为止我已经审计了数百个),LCP 失败几乎总是归结为三个根本原因:

  • 未优化的英雄图或卡片图,通常以完整分辨率提供,格式错误,没有 fetchpriority 提示
  • 渲染阻塞的第三方脚本,联盟追踪器,广告网络,对比小部件在浏览器绘制任何内容之前加载
  • TTFB 膨胀了 LCP 预算,服务器响应缓慢在页面开始加载之前吃掉 600-900 毫秒

第三个是人们低估的。如果你的 TTFB 是 700 毫秒,在浏览器渲染单个像素之前,你已经花掉了近一半的"良好"LCP 预算。主机选择和服务器端缓存不是 DevOps 的问题,是 SEO 的问题。

---

从 TTFB 开始:这首先是一个托管和缓存问题

我上面提到的HostList类型的项目?我做的第一件事是从五个不同的地理位置运行WebPageTest。TTFB一直稳定在680-820ms。网站在弗吉尼亚的共享主机上。他们的大部分有机流量来自英国和德国。

把网站迁移到了一个托管WordPress主机,在伦敦和法兰克福设有边缘节点。配置了完整页面缓存,列表页面的缓存生命周期设置为12小时(数据反正也不经常变化)。在重复请求中TTFB下降到120-180ms,首次缓存未命中时为280-350ms。这一项改动就让LCP减少了约500ms,还没有优化过任何图片。

关于托管方面,我总是检查以下几点:

  1. 全页缓存是否真的在工作?检查X-Cache响应头。如果每个请求都显示MISS,说明你的缓存层没有正常运作。
  2. 源服务器地理位置是否靠近你的主要受众?这听起来很明显。但你会惊讶于这一点多么经常出错。
  3. 是否启用了keep-alive?一些便宜的主机仍然禁用持久连接。在2024年这样做很离奇,但确实会发生。
  4. HTTP/2或HTTP/3是否活跃?运行curl -I --http2 https://yourdomain.com并检查响应中的协议。

在解决TTFB之前不要动图片优化。在一个慢速服务器上优化图片就像给一栋着火的房子粉刷一样。

---

LCP图片问题(以及为什么`fetchpriority`改变了一切)

对。图像。在具有卡片网格布局的列表网站上,LCP 元素几乎总是第一张首屏上方的卡片图像,或英雄横幅。浏览器必须发现它、获取它、解码它并渲染它。这些步骤中的每一个都可能被延迟。

以下是我们在 HostList 项目中实际所做的,按顺序:

  1. 使用 Imagify 的批量转换功能,将所有卡片图像转换为 WebP 格式。在我们使用的卡片缩略图尺寸(280×180px 显示,视网膜屏幕下 2 倍像素)上,平均文件大小下降了 58%,视觉质量没有明显损失。
  2. 在第一张卡片图像上添加了 `fetchpriority="high"`。仅此一项改动就在 WebPageTest 的测试中将 LCP 降低了约 200ms。浏览器停止将其视为普通的懒加载图像,而是立即将其加入预加载扫描器的队列。
  3. 从前两行卡片图像中移除了 `loading="lazy"`。懒加载对折叠线下方的图像非常有效。但在第一个可见行上,它反而有害。它告诉浏览器在图像接近视口时再获取,而此时图像已经在视口内了。
  4. 在首页模板的 `<head>` 中为 hero 图片添加了 `<link rel="preload">` 标签。

这个流程把首页的 LCP 从 3.1 秒降低到了 1.4 秒(在实验条件下)。现场数据在大约 28 天内跟进(这大约是 CrUX 数据在大规模反映变化所需的时间)。

关于响应式图片的说明

如果你向移动设备提供同一张 1400px 宽的图像,你就是在浪费带宽并增加解码时间。正确使用 srcset。我知道这听起来像是 2016 年的话题,但我仍然在大约 40% 经过 Seahawk 的网站上看到这种情况。WordPresswp_get_attachment_image() 函数会自动生成 srcset,但前提是图像上传时分辨率足够高,且主题没有通过 add_filter('max_srcset_width', ...) 禁用它。

---

阻塞渲染的脚本:联盟网站的税收

主机对比网站和列表平台靠联盟营收维生。这意味着有第三方跟踪脚本。Commission Junction、Impact、Awin、自定义像素追踪器,它们堆积起来。我在一个列表网站上数过 14 个独立的第三方脚本来源。每一个都需要单独的 DNS 查询、TCP 连接和 TLS 握手,然后才能收到该脚本的一个字节。

修复方案不是移除这些脚本。你不能这样做,收入取决于它们。修复方案是排序。

没有第三方脚本应该阻塞LCP元素的初始渲染。句号。

在实际操作中,这意味着:

  • 将所有联盟/分析脚本移到DOMContentLoaded事件之后加载,而不是在<head>中。
  • 在你控制的每个脚本上使用asyncdefer属性。
  • 对于你无法控制的脚本(由标签管理器注入),使用 defer 加载 Google Tag Manager 本身。是的,这对大多数联盟跟踪用例是安全的,GTM 自己的文档也承认这种方法。
  • 使用Asset CleanUp Pro或WP Rocket的脚本延迟功能等脚本管理器,将非必要的第三方脚本延迟加载到用户交互(首次滚动或首次点击)时。

在HostList.io重建中,延迟第三方脚本将总阻塞时间从1,840ms减少到290ms。TBT本身不是Core Web Vital,但它与INP的相关性很强,而INP是。

---

字体加载:那个无人谈论的 LCP 隐形杀手

自定义字体会引发特定的故障模式。浏览器渲染你的布局,到达 LCP 文本元素(有时 LCP 是标题而非图像),然后在绘制前等待字体文件。这称为不可见文本闪烁,它会根据字体文件大小和服务器距离延迟 LCP 200ms 到超过一秒。

两件事可以解决这个问题:

  • 在你的 @font-face 声明中加入 `font-display: swap`,浏览器会立即用备用字体渲染,当自定义字体加载完成时再替换。LCP 候选项按时被绘制。
  • 自托管你的字体。Google Fonts 会增加跨域请求。使用 google-webfonts-helper 工具自托管,你可以从自己的域名提供字体,节省额外的连接。

我用那个工具在大约 45 分钟内把一个大型目录网站从 Google Fonts 迁移出来。LCP 改进了 180ms。单独看不是革命性的,但结合其他所有优化,这些边际收益会复合增长。

---

衡量实地中真正重要的指标

CrUX 数据是基础事实。但它只按月更新,且仅适用于流量足够的 URL。对于拥有数千个页面的大型网站,你需要更细粒度的数据。

我在代表性的 URL 样本上使用 PageSpeed Insights API 脚本化测试,通常包括按流量排名前 100 的页面、50 个分类级页面和 20 个"瘦"深目录页面。每月运行一次可以得到适当的性能分布,而不是单点分数。

在 Lighthouse CI 中(我们在为具有开发周期的客户的 CI/CD 管道中运行),我们对以下指标进行断言:

  • LCP ≤ 2.5s(实验室环境,保守目标,因为实际环境通常比实验室环境慢 10-15%)
  • TBT ≤ 300ms
  • CLS ≤ 0.1

但老实说,对于目标是 LCP 低于 1.5 秒的 HostList 类型构建,实验室目标需要更严格。我们在这些项目的 Lighthouse CI 中设置 LCP ≤ 1.8s,一旦 CrUX 赶上进度,通常会在实测数据中产生 1.3-1.5s 的结果。

---

汇总:HostList 的结果

在运行完上述所有操作后——托管迁移、全页面缓存、图像格式转换、LCP 候选项的 fetchpriority、移除首屏行的延迟加载、脚本延迟执行和字体自托管——数据看起来是这样的:

  • TTFB: 780ms → 160ms(中位数,英国访客)
  • LCP(实验室,移动端):4.2s → 1.4s
  • LCP(实际,CrUX,75 百分位):3.8s → 1.6s(迁移后 60 天测量)
  • TBT:1,840ms → 290ms
  • CLS:原本就不错,为 0.03,未改变

并非每个网站都能获得 2.8 秒的提升。但我做过的几乎所有大型列表网站都同时存在这些问题,这意味着收益是叠加的。修复一个问题你能获得 300ms 的提升。全部修复你就能获得 2.5 秒。

---

常见问题

托管服务对 LCP 的影响真的那么大吗?

是的,可能比其他任何东西在开始时都重要。如果你的 TTFB 高于 500ms,再多的图像优化也无法让你达到"优秀"LCP。TTFB 是其他一切的基础。先把它降到 200ms 以下,然后再考虑其他的。

我应该使用 CDN 而不是迁移主机吗?

CDN 有助于静态资源交付,如果配置得当,可以降低缓存整页 HTML 的 TTFB。但许多 CDN 设置只缓存资源,不缓存整个 HTML 响应。检查你的 CDN 是否真的在提供缓存的 HTML,还是只在卸载图像。如果是后者,更好的源主机对 LCP 的改进会更大。

`fetchpriority="high"` 现在得到广泛支持了吗?

截至 2024 年,是的,它在 Chrome、Edge 和 Safari(自 Safari 17.2 起)中得到支持。Firefox 支持在 Firefox 132 中推出。对于不支持它的浏览器,它被安全地忽略。将它添加到你的 LCP 图像元素上没有任何缺点。

CrUX 数据需要多长时间才能反映改进?

从真实用户开始体验网站更快版本起,大约需要 28 天。CrUX 使用滚动 28 天窗口。所以如果你今天部署更改,你的字段数据分数在大约一个月后才会完全反映这些改变。如果在优化冲刺的第二天 PageSpeed Insights 仍然显示"需要改进",不用惊慌。

对于列表网站,单一最高影响力的改变是什么?

在几乎每个项目上,都是 TTFB。但第二高的一致是从首屏卡片图像中移除 loading="lazy" 并添加 fetchpriority="high"。这两个操作通常占总 LCP 改进的 40-60%。其他一切都是在这个基础之上的复合收益。

---

大型网站的性能工作主要是基础设施工程。乏味、有条不紊,但当你把 4 秒的 LCP 降低到 1.4 秒,两个月后看到有机流量提升时,会深感满足。没有什么灵丹妙药,只是按正确顺序做出的一系列具体决策。

让服务器变快。然后让 LCP 元素被及早发现和获取。然后让其他一切都为它让路。

← 返回