众所周知,第一印象很重要,不仅是在与人交流上,在构建web体验的时候也是如此。
在web上,一个好的第一印象是决定用户去留的关键。那么问题来了,怎样才能留下好的第一印象,怎样测试你的网站给用户留下的第一印象?
在web上,第一印象也分很多方面:站点设计、视觉体验、速度和响应。
很难用API去测试一个网站的设计和视觉,但却可以测试速度和响应。
测试你的站点给用户的第一印象加载多快,可以通过 FCP
的指标。但在屏幕上绘制像素仅仅是这个故事的一部分,同样重要的,还有你的网站对用户的交互响应有多快。
FID(First Input Delay)
的指标可以帮你测试用户对你站点的交互响应的第一印象。
什么是FID?
FID
测量的是当用户第一次在页面上交互的时候(点击链接、点击按钮或者自定义基于js的事件),到浏览器实际开始处理这个事件的时间。
好的FID得分多少?
75%的用户在100ms以内。
FID具体内容
开发者编写了事件响应代码,我们通常认为这个代码会在事件触发的时候立刻响应。但是从用户角度上看,经常与预期相反,我们在手机上打开一个网页,试图去点击按钮或者滑动页面,然而什么也没有发生。
通常,输入延迟发生在主线程忙的时候,所以浏览器无法响应用户的交互。比较常见的一个原因是,当浏览器在解析和执行一个较大的js文件的时候,浏览器会忙一会。当遇到这种情况的时候,浏览器无法响应事件,因为要处理加载中的js交给它的一些任务。
FID 只是测量事件处理之前的延迟,不能测量时间处理所花费的时间本身,也不包含时间处理之后的UI更新时间。
看一下下图的经典的页面加载的时间线:
上图展示了页面加载过程中,加载了其他资源文件(js或者css),在这些资源文件下载完后,会由主线程去处理。
这导致主线程处于忙碌状态,高亮表示的色块。
较长的 FID
一般发生在 FCP(First Contentful Paint)
和 TTI(Time to Interactive)
之间,因为页面正在渲染内容,还不能交互。为了说明这是怎么发生的,我们将 FCP
和 TTI
在时间线中标注了:
上图我们可以观察到,有3处较长的时间段,在 FCP
和 TTI
之间。如果用户刚好在这些时间段内做了交互,就会产生一个延迟,从点击事件发生开始到主线程空闲,如下图:
由于输入发生在了浏览器忙的过程中,必须等待浏览器处理完手头上的事情,才能响应,等待的时间就是 FID
的值。
如果某一个交互没有事件回调?
FID
测量的是从接收到输入事件开始,到主线程下一次空闲的时间差值。这也意味着,即使没有注册事件监听,FID也能被测量。因为很多用户交互都不需要监听事件,但却需要主线程空闲。
以下html标签都需要在主线程空闲的时候,才能交互:
为什么只考虑第一次输入?
- 第一次输入延迟会成为用户的第一印象,第一印象对整个站点的印象至关重要。
- 最大的交互问题就在页面加载的时候,聚焦改善用户的第一次交互对改善整个站点的交互有重要影响。
- 第一次输入延迟和页面加载之后的输入延迟的优化方案有所不同,分离这些指标,可以为web开发者提供更具体的性能指南。
怎样的算是第一次输入?
FID
测试的是页面加载过程中页面的响应。因此,它仅关注离散的操作(如:点击,轻击、按键)。
其他交互,像滚动和缩放是持续性的操作,具有完全不同的性能约束(而且,浏览器通常会用一个单独的线程来处理它们,以隐藏延迟)。
换句话说,FID
聚焦的是 RAIL
模型中的R (responsiveness),而滚动和缩放更多地是A (animation),它们的性能应该分别评估。
如果用户一直不交互?
并非所有用户在访问你的站点的时候都会产生交互,也并不是所有交互都与 FID
相关。另外,有一些用户在一个不合适的时机产生了交互(主线程忙),而另一些用户在一个非常合适的时机产生了交互(主线程完全空闲)。
这也意味着有一些用户不会有 FID
的值,有一些用户有较低的 FID
,而另一些有较高的 FID
。
为什么只考虑输入延迟?
前面也提到了,FID
测量的只是事件处理之前的延迟。这不包含事件处理自身所花费的时间,也不包含事件处理之后的UI更新时间。
虽然这些时间也很重要,但如果将它们一起算上,开发者可能会为了降低这个数值,采用 setTimeout()
或者 requestAnimatioinFrame()
的方式来异步执行事件回调,将事件处理回调与事件相关的任务分离。结果确实能提升这个指标,但对用户而言,响应更慢了。
开发者可以通过使用 Event Timing API 来捕获更多的事件生命周期,定制自己的指标。
如何测量FID?
由于 FID
只能是用现场数据测试,需要用户的真实交互,最简单的测量方式就是集成 web-vitals 的js库,如下:
import {getFID} from 'web-vitals';
// Measure and log the current FID value,
// any time it's ready to be reported.
getFID(console.log);
分析和上报FID数据
虽然 core web vitals 定义了75%这个阈值,但 FID
的阈值最好是在95% - 99% 之间,因为这些将对应用户在你的站点上的糟糕体验。它会向你展示你最需要改进的地方。
如何改善FID?
一般有以下四个:
- 减少第三方代码的影响
- 减少js的执行时间
- 最小化主线程的工作
- 减少请求数和请求包的大小
具体的优化方案,可以等待后面的文章更新。
总结
FID 测试下来,只要不出意外,基本都在99%以上,除非特别卡的手机,可能产生一丝影响,当然这些测试的前提是手机是安卓8以上的系统,一般这么高版本的系统硬件性能也不会太差。平时我们开发的时候,很少注意FID,但生活中,我们打开一个网页,卡的不能用的时候,这就是FID。