Skip to content

Core Web Vitals

Core Web Vitals(核心网页指标)是 Google 定义的一组衡量用户体验的关键性能指标。这些指标直接影响 Google 搜索排名,包括 LCP(最大内容绘制)、INP(交互到下一帧绘制)和 CLS(累积布局偏移)。本节将详细介绍每个指标的定义、优化策略和 Lighthouse 评分方法。

前置知识

阅读本节前,建议先了解:减少 DOM 节点数

Core Web Vitals 概览

指标全称衡量内容良好阈值
LCPLargest Contentful Paint加载性能<= 2.5 秒
INPInteraction to Next Paint交互性能<= 200 毫秒
CLSCumulative Layout Shift视觉稳定性<= 0.1

LCP(最大内容绘制)

定义

LCP 测量页面主要内容元素变为可见的时间。通常是最大的图片、文本块或视频元素。

HTML 中的 LCP 元素

html
<!-- 可能的 LCP 元素 -->
<h1>大标题文本</h1>                          <!-- 文本块 -->
<img src="hero-banner.jpg" alt="横幅">         <!-- 图片 -->
<video src="intro.mp4" poster="video.jpg">     <!-- 视频 -->
<div style="background: url(bg.jpg)">...</div>  <!-- 背景图片 -->

LCP 优化策略

策略说明
优化服务器响应时间TTFB < 800ms
内联关键 CSS减少渲染阻塞
优化图片WebP/AVIF、压缩、预加载
使用 CDN全球加速
预加载 LCP 元素<link rel="preload">
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>LCP 优化示例</title>

  <!-- 内联关键 CSS -->
  <style>
    body { margin: 0; font-family: sans-serif; }
    .hero { height: 50vh; position: relative; }
    .hero img { width: 100%; height: 100%; object-fit: cover; }
  </style>

  <!-- 预加载 LCP 图片 -->
  <link rel="preload" href="/images/hero.webp" as="image" fetchpriority="high">
</head>
<body>
  <div class="hero">
    <img
      src="/images/hero.webp"
      alt="首屏横幅"
      fetchpriority="high"
      width="1200"
      height="600"
    />
  </div>
</body>
</html>

INP(交互到下一帧绘制)

定义

INP 测量用户交互到页面视觉响应的时间。它取代了 FID(First Input Delay),更全面地衡量页面交互性能。

INP 优化策略

策略说明
减少主线程工作拆分长任务
使用 Web Worker将计算移到后台
避免长任务使用 requestIdleCallback
优化事件处理防抖、节流
减少 DOM 大小减少查询和布局时间
javascript
// 使用 requestIdleCallback 延迟非关键工作
function handleUserClick(event) {
  // 立即处理关键任务(UI 更新)
  updateUI();

  // 延迟非关键任务
  requestIdleCallback(() => {
    logAnalytics(event);
    sendToServer(event);
  });
}

// 长任务拆分
function processLargeData(data) {
  const CHUNK_SIZE = 100;
  let index = 0;

  function processChunk() {
    const chunk = data.slice(index, index + CHUNK_SIZE);
    chunk.forEach(item => processDataItem(item));
    index += CHUNK_SIZE;

    if (index < data.length) {
      // 让出主线程
      setTimeout(processChunk, 0);
    }
  }

  processChunk();
}

CLS(累积布局偏移)

定义

CLS 测量页面加载过程中元素位置的意外移动。用户的视觉体验会因布局偏移而中断。

CLS 评分标准

评分CLS 值用户体验
优秀<= 0.1几乎无感知
需改进0.1 - 0.25有轻微移动
> 0.25明显跳动

常见 CLS 原因及修复

html
<!-- 1. 图片没有尺寸 → 添加 width/height -->
<!-- 错误 -->
<img src="photo.jpg" alt="照片" loading="lazy">
<!-- 正确 -->
<img src="photo.jpg" alt="照片" width="800" height="400" loading="lazy">

<!-- 2. 动态注入内容 → 预留空间 -->
<!-- 错误:广告加载后推开内容 -->
<div id="ad-slot"></div>
<!-- 正确:预留固定空间 -->
<div id="ad-slot" style="min-height: 250px;"></div>

<!-- 3. Web 字体导致 FOIT → 使用 font-display -->
<style>
  @font-face {
    font-family: 'CustomFont';
    src: url('/fonts/custom.woff2') format('woff2');
    font-display: swap;  /* 字体加载前使用后备字体 */
  }
</style>

<!-- 4. 动态内容 → 使用 CSS aspect-ratio -->
<div style="aspect-ratio: 16/9; background: #f0f0f0;">
  <!-- 内容加载前保持比例 -->
</div>

CSS 解决方案

css
/* 为图片预留空间 */
.image-placeholder {
  aspect-ratio: 16 / 9;
  background: #f0f0f0;
  overflow: hidden;
}

.image-placeholder img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 为广告预留空间 */
.ad-slot {
  min-height: 250px;
  width: 300px;
}

/* 字体加载优化 */
@font-face {
  font-family: 'CustomFont';
  font-display: swap;  /* swap | optional | fallback | block */
}

Lighthouse 评分

Lighthouse 性能分类

类别权重指标
FCP15%First Contentful Paint
LCP25%Largest Contentful Paint
TBT25%Total Blocking Time
CLS15%Cumulative Layout Shift
SI15%Speed Index
TTI5%Time to Interactive

运行 Lighthouse

bash
# 使用 Chrome DevTools
# 1. 打开 Chrome DevTools → Lighthouse
# 2. 选择 Performance 类别
# 3. 点击 Analyze page load

# 使用 CLI
npx lighthouse https://example.com --output html --output-path ./report.html

# 使用 npm 包
npm install -g lighthouse
lighthouse https://example.com --view

实战示例:全面优化

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Core Web Vitals 优化示例</title>

  <!-- LCP 优化:内联关键 CSS -->
  <style>
    body { margin: 0; font-family: system-ui, sans-serif; }
    .hero { position: relative; aspect-ratio: 2/1; background: #f0f0f0; overflow: hidden; }
    .hero img { width: 100%; height: 100%; object-fit: cover; }
    .content { max-width: 800px; margin: 0 auto; padding: 2rem; }
    .card { aspect-ratio: 4/3; background: #f0f0f0; overflow: hidden; }
    .card img { width: 100%; height: 100%; object-fit: cover; }
  </style>

  <!-- LCP 优化:预加载首屏图片 -->
  <link rel="preload" href="/images/hero.webp" as="image" fetchpriority="high">
</head>
<body>
  <!-- CLS 优化:使用 aspect-ratio 预留空间 -->
  <div class="hero">
    <img src="/images/hero.webp" alt="首屏横幅" fetchpriority="high" width="1200" height="600" />
  </div>

  <main class="content">
    <h1>Core Web Vitals 优化</h1>
    <p>本页面针对 LCP、INP 和 CLS 进行了全面优化。</p>

    <!-- CLS 优化:为图片预留空间 + 懒加载 -->
    <div class="grid">
      <div class="card">
        <img src="/images/card-1.webp" alt="卡片1" width="400" height="300" loading="lazy" decoding="async" />
      </div>
      <div class="card">
        <img src="/images/card-2.webp" alt="卡片2" width="400" height="300" loading="lazy" decoding="async" />
      </div>
    </div>
  </main>

  <!-- INP 优化:脚本延迟加载 -->
  <script defer src="/js/app.js"></script>
  <script defer src="/js/analytics.js"></script>
</body>
</html>

注意事项

  1. 在真实环境中测试:实验室数据与真实用户数据可能有差异
  2. 关注移动端数据:大多数用户的设备性能低于开发机
  3. LCP 不是唯一的加载指标:同时关注 FCP 和 TTI
  4. CLS 关注整个生命周期:不仅是页面加载时
  5. 定期监控:使用 Google Search Console 监控 Core Web Vitals 数据

最佳实践

  • LCP:预加载关键资源、优化服务器响应、使用现代图片格式
  • INP:拆分长任务、优化事件处理、减少主线程工作
  • CLS:为图片/视频设置尺寸、使用 aspect-ratio、font-display: swap
  • 使用 Lighthouse 定期审计页面性能
  • 使用 Chrome DevTools Performance 面板定位瓶颈
  • 使用 Google Search Console 监控真实用户数据

下一节

继续学习:XSS 防护

参考链接