3、性能分析工具(下):Lighthouse 与 Web Vitals(LCP、FID、CLS)在页面切换场景下的应用

上一讲我们聊了 Chrome DevTools 的 Performance 面板,那是微观层面的「手术刀」。今天要讲的 Lighthouse 和 Web Vitals,更像是宏观的「体检报告」和「健康标准」。

我个人习惯把这两者结合起来用:Lighthouse 做定量评分,Web Vitals 做定性监控。在页面切换场景下,它们能帮你回答三个核心问题:切换到底有多慢?慢在哪里?用户实际体验如何?

3.1 Lighthouse:不只是跑个分

很多人对 Lighthouse 的印象就是「点一下生成报告,看分数」。其实在页面切换优化中,它的价值远不止于此。

3.1.1 模拟模式 vs 真实模式

Lighthouse 提供两种运行模式,我建议你根据场景选择:

模式 适用场景 页面切换相关指标 我的建议
模拟 (Simulated) 开发阶段快速验证 FCP、LCP、TBT、SI 每次改完代码跑一次,看趋势
真实 (DevTools) 上线前最终验收 所有指标 + 真实网络延迟 用 3G 降速模拟弱网切换
我的小技巧: 在模拟模式下,Lighthouse 会「预测」页面加载时间。如果你发现预测的 LCP 比实际慢很多,说明你的页面可能存在「关键资源加载顺序」问题。我在一个 React 项目中就遇到过,Lighthouse 预测 LCP 是 2.1s,实际用户测出来 4.5s——后来发现是字体文件阻塞了渲染。

3.1.2 页面切换场景下的关键审计项

Lighthouse 报告里有几十项审计,但针对页面切换,我只看这几个:

  • Largest Contentful Paint (LCP) — 最大内容绘制时间。页面切换后,用户看到「主要内容」花了多久。
  • Total Blocking Time (TBT) — 总阻塞时间。主线程被 JS 占用的总时长,直接影响切换响应。
  • Speed Index (SI) — 速度指数。页面内容视觉填充的速度,切换时「白屏」的直观体现。
  • Time to Interactive (TTI) — 可交互时间。用户能点击、滚动的时间点。
注意: Lighthouse 的 TBT 和 TTI 是在「模拟加载」下计算的。对于 SPA 的路由切换,Lighthouse 默认只测首次加载。你需要用 --preset=desktop 或手动触发路由切换来测二次加载。我曾经踩过这个坑——优化了半天首次加载,结果用户抱怨的是页面内跳转卡。

3.2 Web Vitals:用户真实体验的「金标准」

Lighthouse 跑分再高,也不代表用户实际体验好。为什么?因为 Lighthouse 是在「受控环境」下测试的。而 Web Vitals 是 Google 基于 Chrome 用户真实数据定义的指标。

说白了,Lighthouse 是「模拟考」,Web Vitals 是「高考」。

3.2.1 三大核心指标

Web Vitals 有三个核心指标,我分别说说它们在页面切换场景下的表现:

指标 全称 页面切换场景含义 良好阈值 差阈值
LCP Largest Contentful Paint 切换后最大元素(图片、视频、大段文本)渲染时间 ≤ 2.5s > 4.0s
FID First Input Delay 用户首次与页面交互(点击、输入)到浏览器响应的延迟 ≤ 100ms > 300ms
CLS Cumulative Layout Shift 切换过程中页面布局的「跳动」程度 ≤ 0.1 > 0.25

3.2.2 页面切换场景的特殊性

你可能会问:「这些指标不是针对首次加载的吗?」

嗯,这里要注意:Web Vitals 的原始定义确实针对「页面加载」。但在 SPA 或 MPA 的页面切换场景下,我们可以这样理解:

  • SPA 路由切换:每次切换相当于一次「迷你加载」。LCP 对应新页面的最大元素,FID 对应切换后用户首次操作,CLS 对应切换过程中的布局偏移。
  • MPA 页面跳转:每次跳转就是一次完整加载,直接套用 Web Vitals 标准。

我的经验: 在优化一个电商 App 的「商品详情页 → 购物车」切换时,我发现 CLS 从 0.05 飙升到 0.35。原因是购物车列表加载时,图片没有预留宽高,导致文字先渲染,图片加载后把文字挤下去了。用户反馈「点加入购物车后页面乱跳」——这就是 CLS 在作祟。

3.3 用工具测量页面切换的 Web Vitals

光知道概念没用,得能测出来。我推荐三种方式:

3.3.1 使用 Performance Observer API

这是最精确的方式,直接在代码里监听:

// 监听 LCP
const lcpObserver = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];
  console.log('LCP:', lastEntry.startTime, lastEntry.element);
});
lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });

// 监听 FID
const fidObserver = new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    console.log('FID:', entry.processingStart - entry.startTime);
  });
});
fidObserver.observe({ type: 'first-input', buffered: true });

// 监听 CLS
let clsValue = 0;
const clsObserver = new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    if (!entry.hadRecentInput) {
      clsValue += entry.value;
    }
  });
  console.log('CLS:', clsValue);
});
clsObserver.observe({ type: 'layout-shift', buffered: true });
注意: 在 SPA 路由切换时,LCP 和 CLS 的监听需要「重置」。我习惯在路由切换完成后,手动调用 performance.clearResourceTimings() 并重新创建观察者。否则你会拿到上一个页面的残留数据。

3.3.2 使用 web-vitals 库

不想手写?用 Google 官方库:

import { onLCP, onFID, onCLS } from 'web-vitals';

// 每次路由切换后重新调用
function reportPageSwitchMetrics() {
  onLCP(console.log, { reportAllChanges: true });
  onFID(console.log);
  onCLS(console.log, { reportAllChanges: true });
}

// 在路由切换完成时调用
router.afterEach(() => {
  reportPageSwitchMetrics();
});

3.3.3 使用 Chrome 开发者工具

快速验证时,我直接用 DevTools 的 Performance 面板,勾选「Web Vitals」:

  • 打开 DevTools → Performance
  • 点击「录制」按钮旁边的齿轮图标
  • 勾选「Web Vitals」
  • 录制一次页面切换
  • 在 Timeline 上会看到 LCP、FID、CLS 的标记点

3.4 知识体系:页面切换性能分析工具全景

下面这张图是我自己梳理的,把今天讲的内容串起来:

页面切换性能分析工具全景图 页面切换性能分析工具全景 分析目标:页面切换卡顿 Lighthouse(模拟环境) Web Vitals(真实用户) Lighthouse 关键审计项 LCP(最大内容绘制) TBT(总阻塞时间) SI(速度指数) / TTI(可交互时间) Web Vitals 三大核心 LCP ≤ 2.5s(主要内容) FID ≤ 100ms(交互响应) CLS ≤ 0.1(布局稳定) 测量方式:Performance Observer / web-vitals 库 / DevTools 输出:量化评分 + 优化建议 + 真实体验数据 建议:Lighthouse 用于开发阶段快速验证,Web Vitals 用于线上真实监控

3.5 实战建议:如何用这套工具链

最后,我分享一个自己常用的工作流:

  1. 开发阶段:每次提交前跑一次 Lighthouse 模拟模式,关注 LCP 和 TBT 的变化趋势。如果 LCP 增加超过 0.5s,我会停下来排查。
  2. 联调阶段:用 DevTools 的 Performance 面板录制真实页面切换,结合 Web Vitals 标记点定位具体瓶颈。
  3. 上线前:在预发布环境用 Lighthouse 真实模式跑一遍,确保所有指标在「良好」范围内。
  4. 线上监控:接入 web-vitals 库,上报到监控平台。设置告警:LCP > 3.0s 或 CLS > 0.2 时自动通知。
曾经踩过的坑: 有一次我优化了 LCP 到 1.8s,但用户反馈还是卡。后来发现是 FID 飙到了 350ms——主线程被一个第三方 SDK 的初始化脚本占用了。Lighthouse 测不出来,因为它在模拟环境下不会模拟用户点击。所以记住:Lighthouse 不能替代真实用户监控。

好了,这一讲的内容就到这里。工具是死的,场景是活的。下次遇到页面切换卡顿,先别急着改代码,用 Lighthouse 和 Web Vitals 把「病根」找出来,再对症下药。