浏览器 fcp指什么,如何测量

4 阅读3分钟

什么是 FCP

FCP(First Contentful Paint,首次内容绘制)是指浏览器从开始加载页面,到第一个内容元素出现在屏幕上所经过的时间。

"内容元素"包括:

文本、图片(含背景图)、SVG、canvas

不包括:

空白的 div、loading spinner 的纯白背景

FCP 评分标准

Google 给出的标准:

时间评级
0 ~ 1.8s🟢 良好
1.8s ~ 3s🟡 需要改善
3s 以上🔴 较差

FCP 和其他指标的区别

FP  (First Paint)            首次绘制,哪怕只画了一个像素
FCP (First Contentful Paint) 首次有意义内容出现  ← 本题
LCP (Largest Contentful Paint) 最大内容元素出现
TTI (Time to Interactive)    页面可交互
时间轴:
|---FP---|---FCP---|--------LCP--------|---TTI---|
  有像素    有内容      主要内容加载完       可交互

FCP 关注的是用户感知到"页面开始有东西了" 的那一刻,比 LCP 更早,是用户体验的第一道关卡。


如何测量 FCP

方式一:Chrome DevTools(开发阶段最常用)

打开 DevTools → Performance 面板 → 录制页面加载

录制后能看到时间轴,FCP 会用绿色竖线标出

或者 Lighthouse 面板,直接生成报告,列出 FCP 具体数值和优化建议。


方式二:Performance API(代码测量,线上监控必用)

// 用 PerformanceObserver 监听 FCP
const observer = new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (entry.name === 'first-contentful-paint') {
      console.log('FCP:', entry.startTime, 'ms')
      
      // 上报到监控系统
      reportToAnalytics({ metric: 'FCP', value: entry.startTime })
      
      observer.disconnect()
    }
  }
})
​
observer.observe({ type: 'paint', buffered: true })

buffered: true 很重要,防止脚本加载慢导致错过 FCP 事件。


方式三:web-vitals 库(推荐,最简单)

Google 官方出的库,封装好了所有核心指标:

import { onFCP, onLCP, onCLS, onTTFB } from 'web-vitals'onFCP((metric) => {
  console.log('FCP:', metric.value, 'ms')
  // 上报
  sendToServer({ name: metric.name, value: metric.value })
})

一行搞定,比手写 PerformanceObserver 简洁很多。


方式四:pagespeed网站

线上真实用户数据(Field Data),输入网址直接分析:

https://pagespeed.web.dev/

这里的数据来自真实用户,比 DevTools 模拟更有参考价值。


FCP 慢的常见原因和优化

原因一:渲染阻塞资源

<!-- ❌ CSS 和 JS 都会阻塞渲染 -->
<head>
  <link rel="stylesheet" href="huge-style.css">
  <script src="huge-bundle.js"></script>
</head><!-- ✅ JS 加 defer/async,CSS 只保留关键部分 -->
<head>
  <style>/* 内联关键 CSS */</style>
  <script src="bundle.js" defer></script>
  <link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
</head>

原因二:服务器响应慢(TTFB 高)

TTFB(首字节时间)高 → FCP 一定高
优化方向:CDN、服务端缓存、接口提速

原因三:资源体积太大

优化方向:
- JS/CSS 压缩、Tree Shaking
- 图片压缩、转 WebP 格式
- 开启 Gzip / Brotli 压缩
- 路由懒加载,减少首屏 JS 体积

原因四:字体加载阻塞文字显示

/* ❌ 默认等字体加载完才显示文字 */
font-display: block;
​
/* ✅ 先用系统字体显示,字体加载完后替换 */
font-display: swap;

原因五:没有服务端渲染

CSR(纯前端渲染):
浏览器下载 HTML → 下载 JS → 执行 JS → 渲染内容
FCP 很晚,因为要等 JS 执行完
​
SSR(服务端渲染):
服务器直接返回带内容的 HTML → 浏览器直接渲染
FCP 很早,因为 HTML 里已经有内容了

面试加分点

FCP 和 LCP 哪个更重要?

都重要但关注点不同。FCP 反映用户"看到东西"的速度,LCP 反映"看到主要内容"的速度。LCP 和用户实际体验更相关,是 Google Core Web Vitals 的核心指标之一,直接影响 SEO 排名。FCP 是 LCP 的前置条件,FCP 慢 LCP 一定慢。

线上监控 FCP 要注意什么?

要区分 P50(中位数)和 P75、P90 等百分位数。Google 建议看 P75,即 75% 的用户体验到的 FCP 值,而不是平均值,因为平均值会被少数极快的请求拉低,掩盖大部分用户的真实体验。

FCP 为 0 或异常小是什么原因?

可能是页面有预渲染或者 Service Worker 缓存,浏览器直接从缓存返回了内容,导致 FCP 极小,这是正常的优化效果,不是 bug。