FID(First Input Delay)
とは何か
FID(First Input Delay)
とは、「サイトの双方向性と反応性に対するユーザーの第一印象1」を計測することを企図した指標。
具体的には、「ユーザが初めにページと対話(≒操作)したときからブラウザが実際にその対話(≒操作)への反応としてイベントハンドラの処理を開始できるまでの時間」とされている。
FID
の目標タイムとしては、100ミリ秒以内を目指すべきとされる。
また、このタイムをほとんどのユーザで体験できることを目指すのであれば、ページロードにおいて75パーセンタイルに当たるところが良い閾値となるとのこと。
なお、この「100ミリ秒以内」という数値について、Webに限らず工業デザイン一般において人間が遅延を感じ始める時間(応答時間の目標上限値)として知られているものでもある。
もっと詳しい話
では、その遅延はどうして起こるのか
一般には、「何かしらの処理が原因でメインスレッド2がビジーになっていて、まだユーザの操作に反応できてない」というのが考えられる。
そして、そのよくある原因の1つとしてブラウザがWebアプリケーションのバカでかいJavaScirptファイルを実行に向けて解釈している最中であるが多い。そしてこの場合、そのでっかいJavaScript内にイベントハンドラが書かれているかもしれないので、ブラウザは何ひとつイベントリスナーを走らせることができない。
(ブラウザ「だからいまその『何をすべきか』を理解してる最中かもだから、ちょっとまって!!」)
もちろん上記の例以外にも、何かしらの重い処理でメインスレッドがビジーになれば、イベントハンドラーの実行が遅れ、遅延の原因となりうるので、なるべくメインスレッドを空けておく、アプリケーションのJSが大きくなりすぎたときは画面・機能ごとなどに分割して負荷を時間的に分散する、などで適宜適切な対策を講じると良い。
ところで、操作に対して何もイベントリスナーを持ってないときはどうなるの?
FID
は、入力イベントが受理されてからメインスレッドが次のアイドルタイムに入るまでの時間を計測するが、これはFID
が何一つイベントリスナーを登録されていなくても計測されるということになる。その理由としてなぜなら、多くのユーザインタラクションがイベントリスナーを必要としないが、挙動にはメインスレッドがアイドル状態になる必要があるから、だそうです。
例えば、下記の全てのHTML要素がユーザインタラクションに先立って実行中のメインスレッドのタスクの完了を待つ必要ある。
- テキストフィールド、チェックボックス、そしてラジオボタン(
<input>
,<textarea>
) - 選択ドロップダウン(
<select>
) - リンク(
<a>
)
なぜ初めの入力だけ遅延を気にするのか
Webページ/アプリケーションの入力遅延は(初回に限らず)いかなる時でもユーザエクスペリエンスの悪化要因となるが、ではなぜ初回の入力遅延だけ特に重要視されているのか。
FID
を紹介する記事では、以下のように説明されている。
- The first input delay will be the user's first impression of your site's responsiveness, and first impressions are critical in shaping our overall impression of a site's quality and reliability.
- The biggest interactivity issues we see on the web today occur during page load. Therefore, we believe initially focusing on improving site's first user interaction will have the greatest impact on improving the overall interactivity of the web.
- The recommended solutions for how sites should fix high first input delays (code splitting, loading less JavaScript upfront, etc.) are not necessarily the same solutions for fixing slow input delays after page load. By separating out these metrics we'll be able to provide more specific performance guidelines to web developers.
- 初回の入力遅延はユーザにとってサイトの応答性に対する第一印象となりやすく、そして第一印象はサイトのクオリティや信頼性などの全体の印象の形成に決定的(な影響を及ぼすもの)となる。
- 我々が今日目にする最大の双方向性の問題はページロードの最中に起こる。それゆえ、まずはサイトの(表示)初期のユーザインタラクションの改善に着目することがWeb全体の双方向性の改善に大きなインパクトをもたらすだろうと信じている。
- (コードスプリッティングや事前にロードされるJavaScriptの削減 等)高い初期入力遅延の改善に推奨されている手法が必ずしも読み込み後の入力遅延にも有効であるとは限らない。(しかし)これらの指標を分離することでより具体的なパフォーマンスガイドラインをWeb開発者に対して提供できるようになるだろう。
何の操作がFID
の対象となり、逆に何がそうでないか
FID
は読み込み中のページの応答性を測定する指標であり、それゆえ、クリックやタップ、キー押下などの個々の操作による入力イベントにフォーカスしているに過ぎない。
その他のインタラクション、例えばスクロールやズーム、は継続的なアクションでありパフォーマンス上の成約とは完全に異なるものである(そしてまた、ブラウザはこれらを別スレッドで処理することでそれらに起因する遅延を隠蔽できていることもしばしばある)。
言い換えれば、FID
はRAILパフォーマンスモデル
におけるR(responsiveness)
に注目し、スクロールやズームはA(animation)
のほうにより関係があり、そしてこれらのパフォーマンスクオリティは分離して評価されるべきである。
もしユーザがサイト内で何一つ操作をしなかったら?
すべてのユーザが訪問したサイトで何かしら操作をするとは限らず、なんなら(前項に記載の通り)すべての操作がFID
に関係しているわけではない。加えて、各ユーザの最初の操作についてもそれぞれタイミングの良し悪しがあったりする。
このことは、あるユーザはFID
値がそもそもなかったり、また別のユーザは偶然良かったり、はたまた逆に悪かったりするということを意味する。
なので、FID
を追って、レポートして、分析するということは、これまで慣れ親しんだ他の指標とは少し異なるかもしれないということになる。
この辺の問題への対処法は後述。
てかそもそもなんで入力「遅延」だけ気にするのか
上述してきたとおり、FID
はイベント処理中の「遅延」のみを計測し、イベント処理そのものの処理時間やイベントハンドラによって起こるUI更新にブラウザがどれだけ時間をかけたかなどは計測されない。
これらの時間がユーザにとって重要であり、またユーザエクスペリエンスに間違いなく影響を及ぼすにもかかわらずFID
に含まれていない理由は、開発者に対し実際にはユーザエクスペリエンスを悪化させるようなその場しのぎの対処法の実装を奨励することになりうるからだ。すなわち例えば、イベントに関連付けられたタスクをそれらから分離するために、イベントハンドラロジックを(setTimeout()
やrequestAnimationFrame()
などを介した)非同期のコールバックでラップしたりなどである。こうなることは指標スコアの改善にはつながっても、ユーザが知覚する応答性は悪化する。
ところが、FID
はイベント遅延において分析しうる要素のうちの「どれだけ遅延したか」のみを計測しているため、イベントサイクルについてより追跡したいと考える開発者にEvent Timing APIを使用した分析に導くことができる。
なお、Event Timing APIを使用した分析手法については、web.devのCustom metricsについての記事が詳しい。
FID
の計測と分析
FID
が計測可能なライブラリ・ツール
- web-vitals(npmライブラリ)
- Web Vitals Chrome Extension(Chrome拡張機能)
- LighthouseおよびChrome DevTools
- Chrome User Experience Report
- PageSpeed Insights
- Search Console (Core Web Vitals report)
JavaScriptでFID
を測ってみる(測れてるとは言ってない)
JavaScriptでのFID
の計測は、Event Timing API
を使用する。
以下の例では、簡易的にPerformanceObserver
に対してfirst-input
をリスンさせログをコンソールに出力している。
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
const delay = entry.processingStart - entry.startTime;
console.log('FID candidate:', delay, entry);
}
}).observe({type: 'first-input', buffered: true});
【注意】: 正確な精度のFIDの計測にはもっと複雑なJavaScriptによる実装が必要。上記の例ではfirst-input
エントリの遅延時間をエントリのstartTime
とprocessingStart
間のタイムスタンプ差分を取ることでFID
とみなしており、ほとんどのケースでそうなるが、かならずしも全てのfirst-input
エントリがFID
の計測に用いるのに適切とは限らない。
Event Timing API
とFID
間の差異
-
first-input
エントリはページのロードがバックグラウンドで行われたものも対象とされるが、FID
の計測では無視されなければならない。(→ 計測すべきでないものが誤計測される) -
first-input
エントリはページが初期入力の発生に先立ってバックグラウンド化された場合でも対象とされるが、FID
の計測ではこれも同様に無視されなければならない。(→ 同上) -
first-input
エントリはブラウザの「戻る」/「進む」時にキャッシュから復元された場合はレポートされないが、FID
の計測においてこれらはユーザエクスペリエンス上個別のページ訪問として計測されなければならない。(→ 計測されるべきものが計測落ちする) -
Event Timing API
はiframe内で発生した入力をレポートしないが、正確なFID
の計測ではこれらも考慮されなければならない。もしサブフレーム内でもEvent Timing API
によってfirst-input
エントリによるレポートを生成し親フレームに集約させていればiframeを含む正確なFID
の計測が可能(親フレーム側でもそれを許可&受け取る必要あり)。
真・JavaScriptでFID
を測ってみる(feat. web-vitals
ライブラリ)
import {getFID} from 'web-vitals';
// これで計測された**正確な**FIDがコンソールに出力されるようになる
getFID(console.log);
以上である。(なんだい?この簡単すぎて拍子抜けするコードは。)
なおセキュリティ上の理由で、このgetFID()
を使った方法でも、「クロスオリジンなiframe」のようなケースにおいて一部FID
を計測できない場合がある。
詳細はweb-vitals
ライブラリのLimitationsの項を参照のこと。
ちなみに、FID
の正確な計測方法を知りたい場合、このgetFID()
のソースコードから確認できる。
FID
データの分析とレポート
前述の通り、FID
値はブレることが予想されるため、FIDをレポートする際には、値分布に気を配り、より高いパーセンタイルにフォーカスするのが重要となる。
全てのCoreWebVitals
におけるパーセンタイル選択のしきい値は75だが、こと
FID
については、サイト内でファーストエクスペリエンスが特に劣悪だったユーザに対応するであろう95〜90パーセンタイルが推奨される。そうすることで、最も改善を必要とする領域があらわになると思われる。
これは、もしデバイスカテゴリやタイプごとにレポートを分類しても、真と言える。例えば、もしレポートをデスクトップとモバイルに分けてレポートしたとしても、FID
値はデスクトップで最もケアすべきは95〜90パーセンタイルのユーザとなるし、またモバイルにおいても最もケアすべきは95〜90パーセンタイルのユーザとなるからだ。
FID
を改善するには
Lighthouse
などのパフォーマンス監査ツールで検査してみて、提案された改善案の中でこの辺あたりで手を付けられそうなものがないか試してみる。
特に、(FID
がfield metric3な指標、 Lighthouse
がlab metric4なツールであるという違いがあるが、)Lighthouse
が診断結果として提案するTotal Blocking Time (TBT)の改善ガイダンスはFID
と同様なので参考にすると良さそう。
もしFID
の改善手法をより深堀りしたいなら、web.devのOptimize FIDの記事が詳しい。
また、FID
の改善につながる個々のパフォーマンステクニックについて知りたいなら、以下が参考になる。
- Reduce the impact of third-party code - web.dev
- Reduce JavaScript execution time - web.dev
- Minimize main thread work - web.dev
- Keep request counts low and transfer sizes small - web.dev
参照
-
この「第一印象」について、wev.devの
FID
の紹介記事では「どれだけ速くサイトが表示されるかについてのユーザへの第一印象はFirst Contentful Paint (FCP)で計測できる。しかしどんなにスクリーン上のピクセルへの描画が速くてもそれはストーリー(=第一印象を良くする)の単なる一部でしかない。同様に重要なこととしてどれだけそれらのピクセルに対してユーザが対話(≒操作)を試みたときへの反応性が挙げられる。」と説明している。 ↩ -
メインスレッドとは、ブラウザでページの描画などを担っている、メインのスレッド。とはいえ、WebWorkerなどでマルチスレッド化していない限りすべての処理がこのスレッドで行われているので、そういうマルチスレッド下でない限り「現在のページのスレッド」って理解でいい。 ↩
-
field metricとは、実際のユーザ環境下で計測される/されたということ。 ↩
-
lab metricとは、ツール下で環境を制限・制御する形でシミュレートして計測される/されたということ。 ↩