跳至主要内容
Rosecraft Studios

网站性能:Core Web Vitals 实用指南

从测量到改进,了解生产应用中的 LCP、INP 和 CLS,以及怎样清楚报告真实结果。

Corey Rosamond · 2026/1/15 · 约 5 分钟阅读

本文为英文原文的简体中文译文。资料和事件日期保留原文发表时的语境;代码示例保持原样。 Read in English

网站性能:Core Web Vitals 实用指南

为什么关注 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"
/>

主要方法:

  1. 优先加载 LCP 图片:在相应 Next.js 版本中使用 priority 预加载。
  2. 比较格式:在可接受画质下比较 AVIF、WebP 和 JPEG。
  3. 匹配图片尺寸:通过 sizes 帮助浏览器下载合适版本。
  4. 测量服务端响应:检查查询时间、缓存行为与托管延迟。

使用 Lighthouse 做可重复的实验室调查。有数据时使用 CrUX,或符合网站同意设置的真实用户监控。模拟浏览器测试不等于真实访问数据。

交互到下一次绘制(INP)

良好阈值:不超过 200 毫秒

INP 在 2024 年 3 月取代 FID。它考虑页面整个生命周期中的交互延迟,而不只看第一次交互。

常见问题包括:

  1. 长 JavaScript 任务:超过 50 毫秒的任务会长时间占用主线程。
  2. 水合工作:为大型客户端界面附加行为可能与用户交互争抢资源。
  3. 事件处理器工作过多:例如点击后触发连锁状态更新。
// 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 按会话窗口衡量意外布局偏移;部分紧随用户输入的偏移会被排除。常见原因包括:

  1. 图片没有尺寸:浏览器不知道该预留多少空间。
  2. 字体较晚加载:自定义字体替换系统字体时,文字重新排版。
  3. 动态内容插入:广告、嵌入或延迟加载内容推开已有元素。
// 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 概述解释了阈值,以及真实数据与实验室工具的差异。

清楚报告结果

有用的前后对比应说明页面、设备、网络、软件版本、测试日期、样本量和具体变更。将实验室分数与真实访问百分位分开,并保存轨迹或报告,让其他人能核对结论。

想知道网站为什么慢?预约性能评估,我们会帮助找出瓶颈并制定修复方案。

作者:Corey Rosamond,Rosecraft 创始人兼首席工程师

继续阅读

订阅工作室邮件

留下邮箱以接收工作室更新。订阅后请检查确认邮件;确认邮件目前使用英文。

了解隐私政策

下一步,从交流开始

把您的问题,变成清晰的下一步。

告诉我们您想开发或改进什么。我们会一起梳理范围、限制和合适的工程方案。

聊聊项目