首次可见与可交互时间

首次可见与可交互时间的区别,以及它们和 SSR、hydration、主线程执行成本之间的关系。

#tech / dev / frontend #type / synthesis #status / growing

[!info] related notes

首次可见与可交互时间

前端性能讨论里,一个很常见的误区是把“用户已经看到东西了”和“页面已经能顺畅交互了”当成同一件事。

一句话定义

首次可见更关心内容什么时候出现在用户眼前;可交互时间更关心页面什么时候已经完成关键脚本执行,并能稳定响应用户操作。

如果面试官问 FCP / TTI / P90 / P95 怎么采集

这题通常不是让你背术语,而是看你知不知道:

  • 指标分别代表什么
  • 前端从哪里拿数据
  • 为什么不能只看平均值

一个更稳的回答是:

FCP 这类前端性能指标,我一般会在真实用户监控里采集,而不是只看本地 Lighthouse。浏览器侧可以通过 PerformanceObserver 或 Web Vitals 方案拿到 FCP、LCP、INP 这类指标;再把数据上报到埋点平台。TTI 更偏实验室指标,真实线上我会更关注用户是否能及时交互,以及长任务、主线程阻塞、Hydration 成本。P90、P95 则不是新指标类型,而是统计口径,表示 90% 或 95% 用户在这个值以内,主要用来观察长尾体验,而不是只看平均值。

这些指标分别是什么

FCP

  • First Contentful Paint
  • 页面首次有内容出现在屏幕上的时间

TTI

  • Time to Interactive
  • 页面从“看见了”到“能稳定交互”的时间
  • 更偏实验室和分析模型里的指标

P90 / P95

  • 不是单独的性能指标名称
  • 是统计分位数
  • 比如 FCP P90,意思是 90% 用户的 FCP 都不超过这个值

为什么不能只看平均值

因为平均值会掩盖长尾问题。

例如:

  • 大多数用户很快
  • 但弱网、低端机、复杂页面用户很慢

如果只看平均值,长尾用户的糟糕体验很容易被藏掉;P90、P95 更适合观察这类问题。

浏览器侧一般怎么采集

FCP

常见做法是通过 PerformanceObserver 观察 paint 事件:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.name === 'first-contentful-paint') {
      console.log('FCP:', entry.startTime)
    }
  }
})

observer.observe({ type: 'paint', buffered: true })

更稳的工程做法

  • 浏览器侧采集
  • 带上设备、网络、页面路由、用户环境
  • 上报埋点平台
  • 后台再聚合成 P50 / P90 / P95

TTI 为什么现在更容易被谨慎使用

TTI 很适合帮助理解“看见”和“能点”的区别,但它并不是现在最主流的真实用户指标。

工程上更常结合:

  • FCP / LCP 看可见速度
  • INP 看交互响应
  • 长任务 / 主线程阻塞看为什么点不动

所以如果面试官问到 TTI,不要只背定义,最好顺手提一句它更偏分析模型,而真实线上还要结合别的指标一起看。

为什么这两个时间点要分开理解

  • 页面可以先显示内容,但还没完成客户端接管
  • 页面也可能看起来已经完整,但主线程仍然很忙
  • 所以“看得见”不等于“点得动”

它和 SSR、hydration 的关系

  • SSR 或 SSG 往往更容易把首次可见时间提前
  • 但页面要真正可交互,还要看 JavaScript 下载、执行和 hydration 成本
  • 如果客户端接管很重,用户就可能经历“先看见,后能点”

一个典型现象

有些页面会出现这种体验:

  • 页面内容很快出现
  • 但按钮点了没反应,或者要等一下才有反应

这通常说明:

  • 首次可见做得不错
  • 但主线程仍然很忙,或者 hydration 还没完成

为什么它对优化很重要

  • 前端优化不能只看一个时间点
  • 如果只追求“更早显示内容”,但忽略 JS 体积、主线程阻塞和客户端接管成本,用户仍然可能觉得“页面看起来快,但操作起来不快”
  • 只优化首屏直出,不代表用户体感一定好
  • 只压缩包体,也不代表首屏内容出现得够早
  • 真正好的体验通常要同时兼顾可见和可交互

面试里可以顺手加分的一句

我不会只看实验室里的一次跑分,还会看真实用户上报,再按 P50、P90、P95 分层看,因为性能问题往往先出现在长尾环境里。

常见误区

  • 把 SSR 等同于“页面一定更快”
  • 只看页面有没有显示,不看点击是否及时响应
  • 只讨论包大小,不讨论主线程阻塞和接管成本

最短记忆方式

先看到页面,不代表已经能顺畅操作页面。

面试要点

来自 first-paint-vs-time-to-interactive-interview-question 的面试视角整理。

一句话回答

首次可见关注内容何时出现在屏幕上,可交互时间关注页面何时完成关键脚本执行并能及时响应操作;两者相关,但不是同一个指标,也经常不是同一个优化方向。

最稳的回答主线

  • 页面先显示,不代表已经能交互
  • SSR 更容易优化首屏可见
  • 但真正可交互还要看 JavaScript 执行和 hydration 成本
  • 所以性能优化不能只盯“先显示出来”

一个更完整的面试表达

可以这样答:

首次可见关注的是“用户什么时候先看到内容”,可交互时间关注的是“页面什么时候已经完成关键脚本执行,并且能稳定响应用户操作”。
两者相关,但不是一回事。SSR 往往更容易把首次可见提前,但如果 JavaScript 很重、主线程很忙、hydration 成本高,页面依然可能出现“已经显示了,但还不够快能点”的情况。

一个典型场景

如果一个 SSR 页面:

  • 文章正文很快就显示出来
  • 但搜索框、筛选按钮、展开收起要过一会儿才顺畅

那通常说明:

  • 可见时间做得不错
  • 但可交互时间还没真正压下来

面试里容易加分的一句

有些 SSR 页面首屏内容出来很快,但因为客户端接管和主线程执行太重,用户会感受到“看起来快,点起来不快”。

常见追问

  • 为什么页面已经出现了,但点击还是卡
  • SSR 为什么不等于交互也更快
  • 主线程阻塞和可交互时间是什么关系

最短记忆方式

能看见是第一步,能顺畅点才算真正到位。

创建于 2026/3/19 更新于 2026/5/27