Corey Rosamond · 2026/1/15 · 约 5 分钟阅读
本文为英文原文的简体中文译文。资料和事件日期保留原文发表时的语境;代码示例保持原样。 Read in English

为什么关注 Core Web Vitals
Core Web Vitals 描述加载、响应速度和视觉稳定性,有助于发现真实使用流程中的阻力。实验室高分不代表每位用户都有良好体验,也不保证搜索排名或转化。
本文介绍测量方法,不声称本站取得某个 Lighthouse 分数,也不发布未经验证的客户基准。
三个关键指标
最大内容绘制(LCP)
良好阈值:不超过 2.5 秒
LCP 测量最大可见内容元素——通常是主视觉图片或标题——出现所需的时间,与用户对加载的感受密切相关。
// Bad: Unoptimized hero image blocks LCP
<img src="/images/hero.png" alt="Hero" />
// Good: Optimized with next/image, priority loading
import Image from 'next/image';
<Image
src="/images/hero.webp"
alt="Hero section showcasing our engineering work"
width={1200}
height={630}
priority
sizes="100vw"
/>
主要方法:
- 优先加载 LCP 图片:在相应 Next.js 版本中使用
priority预加载。 - 比较格式:在可接受画质下比较 AVIF、WebP 和 JPEG。
- 匹配图片尺寸:通过
sizes帮助浏览器下载合适版本。 - 测量服务端响应:检查查询时间、缓存行为与托管延迟。
使用 Lighthouse 做可重复的实验室调查。有数据时使用 CrUX,或符合网站同意设置的真实用户监控。模拟浏览器测试不等于真实访问数据。
交互到下一次绘制(INP)
良好阈值:不超过 200 毫秒
INP 在 2024 年 3 月取代 FID。它考虑页面整个生命周期中的交互延迟,而不只看第一次交互。
常见问题包括:
- 长 JavaScript 任务:超过 50 毫秒的任务会长时间占用主线程。
- 水合工作:为大型客户端界面附加行为可能与用户交互争抢资源。
- 事件处理器工作过多:例如点击后触发连锁状态更新。
// Bad: Heavy computation in click handler
function handleFilter(tag: string) {
const filtered = allPosts
.filter((p) => p.tags.includes(tag))
.sort((a, b) => b.date - a.date)
.map((p) => ({ ...p, excerpt: generateExcerpt(p.content) }));
setFilteredPosts(filtered);
}
// Good: Memoize expensive computations, defer non-critical work
const filteredPosts = useMemo(
() => allPosts.filter((p) => activeTag === 'all' || p.tags.includes(activeTag)),
[allPosts, activeTag],
);
减少不必要的客户端 JavaScript 可能有帮助,也要检查真实交互中的长任务、事件处理和渲染成本。先测量,再选择优化。
累积布局偏移(CLS)
良好阈值:不超过 0.1
CLS 按会话窗口衡量意外布局偏移;部分紧随用户输入的偏移会被排除。常见原因包括:
- 图片没有尺寸:浏览器不知道该预留多少空间。
- 字体较晚加载:自定义字体替换系统字体时,文字重新排版。
- 动态内容插入:广告、嵌入或延迟加载内容推开已有元素。
// Bad: Image causes layout shift
<img src="/photo.jpg" alt="Team photo" />
// Good: Explicit dimensions prevent shift
import Image from 'next/image';
<Image
src="/photo.jpg"
alt="Team photo"
width={800}
height={600}
className="rounded-lg"
/>
通过 next/font 自托管字体,并选择合适的备用字体度量,可以减少加载和布局问题。使用 display: swap 时,字体加载前仍可能先显示备用文字:
import { Poppins, Inter } from 'next/font/google';
const poppins = Poppins({
subsets: ['latin'],
weight: ['600', '700', '800'],
variable: '--font-heading',
display: 'swap',
});
性能检查清单
以此为起点,根据页面与受众调整性能预算。
图片
- 使用
next/image并明确width和height。 - 主视觉 / LCP 图片配置合适的优先加载。
- 首屏下方图片使用
loading="lazy",这也是 Next.js 图片的默认行为。 - 比较 AVIF、WebP,并保留合适的 PNG / JPEG 回退。
- 按内容和目标网络连接设置并测量图片预算。
JavaScript
- 默认采用 Server Components,减少组件自身的客户端代码。
- 仅对需要交互的组件使用
"use client"。 - 通过
dynamic()拆分大型组件。 - 打包中不保留未使用依赖。
- 用
@next/bundle-analyzer检查实际打包结果。
CSS
- Tailwind 在构建时仅生成检测到的工具类。
- 避免阻塞渲染的外部样式表。
- 检查生产构建实际如何加载样式。
- 动画优先使用可合成的
transform和opacity。
字体
- 自托管字体,并检查备用度量是否造成布局偏移。
- 使用
display: swap渐进显示文字。 - 只加载实际使用的字重。
- 预加载主要标题字体。
在生产中测量
通过 web-vitals 库记录真实访问的 LCP、INP 和 CLS,按网站要求处理数据收集及用户同意。保留指标名称、数值、页面上下文和采样时期,避免包含表单个人信息或保密 URL。
评估第 75 百分位,并区分移动端和桌面端。若某页 CrUX 流量不足,应说明局限,而不是把没有结果当成通过。Web Vitals 概述解释了阈值,以及真实数据与实验室工具的差异。
清楚报告结果
有用的前后对比应说明页面、设备、网络、软件版本、测试日期、样本量和具体变更。将实验室分数与真实访问百分位分开,并保存轨迹或报告,让其他人能核对结论。
想知道网站为什么慢?预约性能评估,我们会帮助找出瓶颈并制定修复方案。