首次可见与可交互时间
首次可见与可交互时间的区别,以及它们和 SSR、hydration、主线程执行成本之间的关系。
[!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 为什么不等于交互也更快
- 主线程阻塞和可交互时间是什么关系
最短记忆方式
能看见是第一步,能顺畅点才算真正到位。