IT
🚀

实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒

一份关于实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒的实用指南,包含清晰的检查清单、需要关注的关键风险,以及面向希望在行动前比较方案的读者的后续步骤。

实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒

重点摘要

  • LCP(Largest Contentful Paint,最大内容绘制)是直接影响 Google 搜索排名的核心指标。
实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒
  • 通过依次应用图片优化、字体加载策略和代码拆分,LCP 从 3.0 秒降到了 1.2 秒。
  • 通过为图片和广告区域指定明确尺寸并消除布局偏移,CLS 从 0.28 改善到 0.04。
  • 基于一个真实上线的 Next.js 项目,但同样的原则也适用于 React 和 Vue 项目。

引言 —— 为什么是 Core Web Vitals

当 Google 在 2021 年推出 Page Experience 更新时,Core Web Vitals 不再只是简单的 UX 指标,而是成为了 SEO 排名因素。此后,Google 持续提高这些信号的权重,并且截至 2024 年,INP(Interaction to Next Paint)已完全取代 FID,成为评估指标。

我运营的一个电商项目,就在六个月前,PageSpeed Insights 移动端得分还低得可怜,只有 38 分。LCP 为 3.0 秒,CLS 为 0.28,INP 为 320ms,三项指标全部处于“Needs Improvement”区间。本文记录了扭转这些数字的完整过程。


如何快速理解三项 Core Web Vitals?

实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒 visual 2

LCP —— 页面“第一印象”的速度

LCP 衡量视口中最大的内容元素(通常是首屏主图或 H1 文本)完成渲染所需的时间。Google 对 Good 的阈值是 2.5 秒或更短;超过 4.0 秒则属于 Poor。

在电商网站中,首屏横幅图片几乎总是 LCP 候选元素。如果这张图片加载得太慢,其他所有优化都会失去意义。

CLS —— 布局是否会“跳动”?

CLS(Cumulative Layout Shift,累计布局偏移)衡量页面加载过程中元素发生意外位移的程度。延迟加载的广告横幅,或没有明确尺寸的图片,都会导致 CLS 飙升。0.1 或以下 是 Good 阈值。

INP —— 页面响应用户输入有多快?

INP 衡量所有交互的响应延迟,包括点击、轻触和键盘输入。它在 2024 年 3 月取代了 FID,200ms 或以下 是 Good 阈值。沉重的 JavaScript bundle 会阻塞主线程,并使 INP 变差。


诊断问题 —— 初始测量

实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒 visual 3

优化前准确记录指标是起点。按顺序使用了以下工具:

  1. 1PageSpeed Insights — 同时提供现场数据(真实用户数据)和实验室数据(Lighthouse)
  2. 2Chrome DevTools > Performance tab — 检查渲染时间线和 LCP 候选元素
  3. 3WebPageTest — 从 CDN 边缘服务器进行真实环境测量,并通过 filmstrip 进行视觉确认
  4. 4Vercel Analytics / Sentry — 从真实用户会话中收集 Core Web Vitals

诊断将瓶颈缩小到三个方面:

  • Hero image — 4.2MB JPEG,通过 标签直接插入,未做任何优化
  • Google Fonts — 通过 @import 同步加载 3 个字体系列
  • Bundle size — 1.8MB 主 chunk,包含多个未进行 tree-shaking 的库

哪三种方法将 LCP 从 3.0s 降到了 1.2s?

实践中提升 Core Web Vitals —— 我如何将 LCP 从 3 秒降到 1.2 秒 visual 4

方法 1 — 图片优化和预加载

这是影响最大的一项。Hero image 的处理方式被彻底重新设计。

之前

html
<img src="/banner.jpg" alt="Main Banner" />

之后 — Next.js Image Component + WebP 转换

jsx
import Image from 'next/image';

<Image
  src="/banner.webp"
  alt="Main Banner"
  width={1920}
  height={800}
  priority          // LCP target images must always have priority
  quality={80}
  sizes="(max-width: 768px) 100vw, 1920px"
/>

仅添加 priority prop,就会让 Next.js 自动为该图片注入一个 标签。转换为 WebP 后,文件大小从 4.2MB 降到 340KB,约减少 92%。

对于纯 HTML/React 项目,可以直接在 中添加 preload 标签:

html
<link
  rel="preload"
  as="image"
  href="/banner.webp"
  type="image/webp"
/>

这一个改动就将 LCP 从 3.0s 降到了 1.8s。

方法 2 — 字体加载策略

通过 @import 加载 Google Fonts 会导致浏览器暂停 CSS 解析并发起字体请求。这段等待时间会显著增加 LCP。

之前

html
<style>
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
</style>

之后 — + display=swap + 自托管

html

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

<link
  href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"
  rel="stylesheet"
  media="print"
  onload="this.media='all'"
/>

使用 media="print",再在加载完成时切换为 media="all",可以让字体 CSS 异步加载而不阻塞渲染。display=swap 会在网页字体加载期间立即显示备用字体,确保文本保持可见。

为了获得最佳性能,自托管字体可以完全消除 Google Fonts 的往返请求:

css
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-regular.woff2') format('woff2');
}

这一步将 LCP 从 1.8s 降到了 1.4s。

方法 3 — 代码拆分与包体优化

1.8MB 的主 chunk 意味着用户必须先下载并解析将近 2MB 的 JavaScript,页面才能变得可交互。

采取的关键措施:

  1. 1动态导入 — 仅在需要时加载大型库:
jsx
// Before: always loaded
import Chart from 'chart.js';

// After: loaded only when the chart component is actually rendered
const Chart = dynamic(() => import('chart.js'), { ssr: false });
  1. 1Tree-shaking 审计 — 将 import _ from 'lodash' 替换为单个函数导入:
js
// Before: loads entire lodash library
import _ from 'lodash';

// After: loads only debounce
import debounce from 'lodash/debounce';
  1. 1第三方脚本懒加载 — 将分析工具和聊天组件脚本延后到页面可交互后再加载:
html

经过包体优化后,主 chunk 大小从 1.8MB 降到 620KB,LCP 从 1.4s 改善到 1.2s


如何将 CLS 从 0.28 降到 0.04?

造成 CLS 的两个主要问题是广告,以及没有明确尺寸的图片。

广告区域:提前预留空间

css
/* Reserve minimum height so ad slot never causes layout shift */
.ad-container {
  min-height: 90px;  /* banner ad */
  min-width: 728px;
}

图片:始终指定 Width/Height

jsx
/* Before: no dimensions → causes layout shift during load */
<img src="/product.jpg" alt="Product" />

/* After: explicit dimensions → browser reserves space */
<Image
  src="/product.jpg"
  alt="Product"
  width={400}
  height={300}
/>

动态内容:使用占位元素

jsx
// Show skeleton placeholder while data is loading
{isLoading ? (
  <div className="h-48 bg-gray-200 animate-pulse rounded" />
) : (
  <ProductCard data={data} />
)}

这三项改动将 CLS 从 0.28 降到了 0.04


结果汇总

指标优化前优化后变化
LCP3.0s1.2s-60%
CLS0.280.04-86%
INP320ms95ms-70%
PageSpeed Mobile3891+53 分

检查你自己网站的 Core Web Vitals

使用这些工具测量你当前的得分:


常见问题 (FAQ)

Q1. 改善 Core Web Vitals 会直接提升搜索排名吗?

Core Web Vitals 是 Google 官方排名因素之一。Google 已公开确认它们是 Page Experience 信号。不过,内容质量和反向链接等其他因素仍然权重更高,因此 Core Web Vitals 优化应被视为必要条件,而不是保证。

Q2. 哪个 Core Web Vitals 指标对排名影响最大?

LCP 对用户最直观,并且对跳出率的影响最直接,因此会间接影响排名。CLS 也会直接影响用户体验,所以两者都是高优先级的优化目标。INP 作为较新的指标,其影响力仍在逐步确立中。

Q3. 如何检查我的 LCP 元素?

打开 Chrome DevTools,进入 Performance 标签页,录制一次页面加载,然后在时间轴中查找“LCP”。或者,运行 PageSpeed Insights,它会明确告诉你哪个元素是 LCP 候选元素。

Q4. Google Fonts 会影响 Core Web Vitals 吗?

会。通过 @import 加载 Google Fonts 会阻塞渲染,也是导致 LCP 下降的常见原因。强烈建议使用 并结合 display=swap,或改为自托管字体。

Q5. Next.js 对 Core Web Vitals 有多大帮助?

帮助相当明显。Next.js 内置了自动图片优化(WebP 转换、延迟加载、尺寸优化)、字体优化(next/font)以及基于路由的代码拆分。这些功能即使不做额外配置,也能显著改善 Core Web Vitals。

Q6. Core Web Vitals 应该多久检查一次?

建议至少每月监测一次。PageSpeed Insights 反映的是过去 28 天收集的真实用户数据,因此改动需要一段时间才会体现出来。相比一次性测量,使用 Google Search Console 持续跟踪现场数据趋势更实用。

🔧 相关免费工具

下一步

从本指南继续

相关