前端性能指标
FCP、LCP、TTI、CLS、FID 等 Web Vitals 指标的含义与测量
问题
解释前端性能优化中的关键指标:FCP、LCP、TTI、CLS、FID,以及如何测量它们。
解答
指标概览
| 指标 | 全称 | 含义 | 良好标准 |
|---|---|---|---|
| FCP | First Contentful Paint | 首次内容绘制 | < 1.8s |
| LCP | Largest Contentful Paint | 最大内容绘制 | < 2.5s |
| FID | First Input Delay | 首次输入延迟 | < 100ms |
| CLS | Cumulative Layout Shift | 累积布局偏移 | < 0.1 |
| TTI | Time to Interactive | 可交互时间 | < 3.8s |
1. FCP(首次内容绘制)
页面首次渲染出任何文本、图片、非空白 canvas 或 SVG 的时间。
// 使用 Performance API 获取 FCP
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') {
console.log('FCP:', entry.startTime, 'ms');
}
}
});
observer.observe({ type: 'paint', buffered: true });
2. LCP(最大内容绘制)
视口内最大的图片、文本块或视频渲染完成的时间。这是 Core Web Vitals 的核心指标。
// 监听 LCP
const lcpObserver = new PerformanceObserver((list) => {
const entries = list.getEntries();
// 取最后一个,因为 LCP 可能会更新
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime, 'ms');
console.log('LCP 元素:', lastEntry.element);
});
lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
3. FID(首次输入延迟)
用户首次与页面交互(点击、触摸、按键)到浏览器响应的延迟时间。
// 监听 FID
const fidObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// processingStart - startTime = 输入延迟
const delay = entry.processingStart - entry.startTime;
console.log('FID:', delay, 'ms');
}
});
fidObserver.observe({ type: 'first-input', buffered: true });
注意:FID 已被 INP(Interaction to Next Paint)取代,成为新的 Core Web Vitals 指标。
4. CLS(累积布局偏移)
页面生命周期内所有意外布局偏移的累积分数。
// 监听 CLS
let clsValue = 0;
const clsObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// 只计算非用户输入导致的偏移
if (!entry.hadRecentInput) {
clsValue += entry.value;
console.log('当前 CLS:', clsValue);
}
}
});
clsObserver.observe({ type: 'layout-shift', buffered: true });
5. TTI(可交互时间)
页面完全可交互的时间点,需满足:
- 已触发 FCP
- 事件处理器已注册
- 页面在 5 秒内响应用户交互
// TTI 没有直接的 API,可以使用 Google 的 tti-polyfill
// 或通过 Lighthouse 测量
// 简化版本:监听 load 事件后的长任务
const ttiObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// 长任务(>50ms)会阻塞交互
console.log('长任务:', entry.duration, 'ms');
}
});
ttiObserver.observe({ type: 'longtask', buffered: true });
使用 web-vitals 库
Google 提供了官方库简化测量:
import { onFCP, onLCP, onFID, onCLS, onINP } from 'web-vitals';
// 收集所有指标
onFCP(console.log);
onLCP(console.log);
onFID(console.log);
onCLS(console.log);
onINP(console.log); // FID 的替代指标
// 上报到分析服务
function sendToAnalytics(metric) {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
});
// 使用 sendBeacon 确保页面卸载时也能发送
navigator.sendBeacon('/analytics', body);
}
onLCP(sendToAnalytics);
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
优化方向
| 指标 | 优化方法 |
|---|---|
| FCP | 减少阻塞渲染的资源、内联关键 CSS、预加载字体 |
| LCP | 优化图片加载、预加载 LCP 元素、使用 CDN |
| FID/INP | 拆分长任务、延迟非关键 JS、使用 Web Worker |
| CLS | 为图片/视频设置尺寸、避免动态插入内容、使用 hd18w 动画 |
| TTI | 代码分割、延迟加载、减少主线程工作 |
关键点
- Core Web Vitals 包含 LCP、CLS、INP 三个指标,是 Google 搜索排名因素
- FCP 反映首屏速度,LCP 反映主要内容加载速度
- CLS 衡量视觉稳定性,为图片设置宽高是最简单的优化
- FID/INP 衡量交互响应,长任务(>50ms)是主要影响因素
- 使用
web-vitals库 +sendBeacon进行真实用户监控(RUM)
目录