INPが「改善が必要」なときに遅い操作を特定して直す手順
ページを開いたときは速い。なのに Search Console では INP が「改善が必要」と出る。——この食い違いは珍しくありません。INP が見ているのは読み込みの速さではなく、開いたあとの操作に画面が応えるまでの時間だからです。
答えを先に書きます。直す対象は「ページ」ではなく「遅い操作」です。遅い操作を1つ特定し、その操作の時間を3つの区間に分け、いちばん長い区間に効く手を打つ。順番を守れば、闇雲にスクリプトを削る必要はありません。
FID が良かったのに、INP で引っかかる理由
INP(Interaction to Next Paint)は、操作をしてから画面に次の変化が出るまでの待ち時間を測る指標です。web.dev の告知(2024年3月12日更新)で、INP は FID(First Input Delay)に代わってコアウェブバイタルの正式な指標になりました。
違いは測る範囲です。web.dev の説明では、FID が測っていたのはページで最初の1回の操作の「処理が始まるまでの待ち時間」だけでした。INP はページ上のすべての操作を対象にし、待ち時間に加えて、イベント処理の実行時間、次の画面が描かれるまでを含めて測ります。
だから、FID では見えなかった遅さが出てきます。
たとえば、ページを開いて最初のクリックは軽いメニュー開閉だった。でも2回目以降に押す絞り込みボタンが重い。FID ならこの重さは測定対象の外でした。INP では、滞在中に起きたクリック・タップ・キー入力の中でいちばん遅かった操作(外れ値は除く)がそのページの値になります。値が確定するのは、利用者がページを離れたときです。
判定の目安は次のとおりです(web.dev の INP 解説より)。
| INP の値 | 判定 |
|---|---|
| 200ミリ秒以下 | 良好 |
| 200ミリ秒を超え、500ミリ秒以下 | 改善が必要 |
| 500ミリ秒を超える | 不良 |
ここで1つ注意があります。この基準は1回の操作ではなく、実際の利用者の体験の分布にかかります。web.dev の告知では「INP の体験の少なくとも75%が200ミリ秒未満で応答すること」が「良好」の条件として書かれています。手元で1回押して速かったから大丈夫、とはなりません。遅い端末を使う利用者が一定の割合いれば、そちらが判定を決めることがあります。
INP に含まれない操作もある
誤解されやすいのがスクロールです。
web.dev の INP 解説には、ホバー、ズーム、スクロールは INP の観測対象ではないと明記されています。対象はマウスのクリック、タッチ画面のタップ、キー入力です。ただし、これらの操作の中にクリックやタップ、キー入力を伴う変形がある場合は、その部分が対象になりうる、という但し書きも添えられています。
つまり「スクロールがカクつくから INP が悪い」とは限りません。スクロールのカクつきは別の問題として扱い、INP の調査ではまず押す・打つ操作を疑います。
遅い操作を1つに絞るまでの6ステップ
以下が全体の流れです。ステップ1〜2が「どこが遅いか」、3〜5が「なぜ遅いか」、6が「直ったか」に当たります。
- 現場のデータで対象を決める。Search Console のウェブに関する主な指標レポート、または PageSpeed Insights の実ユーザーのデータ(CrUX:Chrome の利用者から集めた体験データ)を見ます。web.dev によれば、CrUX で得られるのは少なくともサイト全体(オリジン)単位の INP で、場合によっては URL 単位のデータも得られます。まずは「改善が必要」と出ている URL、またはそのグループの代表ページを1つ選びます。
- 候補の操作を書き出す。CrUX は問題があることは教えてくれても、何が原因かまでは教えてくれません(web.dev の INP 解説より)。そこで、そのページで利用者が押しそうな操作を列挙します。絞り込みボタン、タブ切り替え、アコーディオン、フォームの入力欄、カートに入れるボタン、などです。web.dev の最適化ガイドは、可能なら実利用者の計測(RUM:実際の訪問者のブラウザで計測する仕組み)を使うことを勧めています。RUM があれば、どの操作が遅いかを直接見られる場合があります。
- 開発者ツールで再現して記録する。Chrome DevTools の「パフォーマンス」パネルで記録を開始し、候補の操作を実際に押して止めます。手元の高性能な PC では再現しないことが多いので、CPU の速度を落とす設定で試すと遅さが見えやすくなります。web.dev の最適化ガイドも、現場データで遅い操作の見当がついてから試験環境(ラボ)で手動再現し、そのうえで最適化に進む順番を示しています。
- 操作の時間を3つの区間に分ける。記録の中の該当操作を、①入力の遅延、②処理時間、③表示の遅延 に分けて、どこが長いかを見ます(詳細は次の表)。
- いちばん長い区間に効く手を打つ。3区間すべてを一度に直そうとしないことです。長い区間から順に手を入れます。
- 現場のデータで確かめる。手元の記録で短くなっても、判定が変わるのは実利用者のデータが入れ替わってからです。現場データは一定期間の集計なので、直した直後には変化が見えないことがあります。
ラボの計測ツールについて1点。実ユーザーのデータとラボの診断は別物です。web.dev によれば、ラボのツールの中には読み込みだけを観測して操作をしないため、INP を出さないものがあります。その場合、TBT(Total Blocking Time:読み込み中にメインスレッドがふさがった合計時間)が代わりの目安になりえますが、INP の代わりそのものではありません。ラボで問題なしと出ても、現場の INP が悪いことは普通に起こります。
3つの区間と、それぞれの打ち手
web.dev は1回の操作を3つの区間に分けて説明しています。入力の遅延は「操作のための処理が始まるまで」、処理時間は「すべての処理(コールバック)が終わるまで」、表示の遅延は「処理が終わってから画面に次のフレームが出るまで」です。
| 区間 | 記録で見えるサイン | 主な原因 | 最初に試す打ち手 |
|---|---|---|---|
| ①入力の遅延 | 操作の直前から別のタスクが走っている | 読み込み中のスクリプトの解析・コンパイル・実行、fetch の処理など、操作と関係ない仕事がメインスレッドを占有 | 読み込み時の重いスクリプトを減らす・後回しにする。サードパーティタグの数と読み込み順を見直す |
| ②処理時間 | クリックのイベント処理そのものが長い1本のタスクになっている | イベントハンドラの中で、画面更新・データ整形・計測送信などを全部まとめてやっている | 処理を別タスクに分割し、画面に見える更新を先に、それ以外を後に回す |
| ③表示の遅延 | 処理後のスタイル再計算・レイアウトが長い | DOM(ページの部品の木構造)が大きい、スタイルを書き換えた直後に同じタスクで読み出している | DOM を小さくする、読み書きを分ける、画面外の描画を遅らせる |
各行をもう少し掘ります。
①入力の遅延は「押した瞬間に、ブラウザが別の仕事で手がふさがっている」状態です。web.dev の最適化ガイドによると、スクリプトの読み込み・解析・コンパイルといったメインスレッド上の活動が原因で、入力の遅延はかなり長くなることがあります。スクリプトの大きさによっては、この作業がメインスレッド上で長いタスクになり、ほかの操作への反応を遅らせます。読み込み直後に押される操作(ファーストビューのボタン、ハンバーガーメニュー)で起きやすいのはこのためです。
②処理時間は、自分たちのコードの中身です。web.dev のガイドは、イベント処理を減らしきれない場合、その仕事を別々のタスクに分割することを次の手として挙げています。まとまった仕事がメインスレッドをふさぐ長いタスクになるのを防ぐためです。分割の手段の1つが setTimeout で、渡した処理は新しいタスクとして実行されます。
③表示の遅延は見落とされがちです。処理が速くても、その結果を描くのに時間がかかれば INP は伸びます。web.dev によれば、DOM が非常に大きくなると描画の作業量もそれに比例して増える傾向があります。また、JavaScript でスタイルを更新した直後に同じタスクの中でその値を読み出すと、レイアウト計算が同期的に走ります(レイアウトスラッシング)。これは DevTools のパフォーマンスパネル上で、該当箇所の右上に赤い三角のマークが付く形で示されます。画面外の要素が多いページなら、CSS の content-visibility で画面に近づくまで描画を遅らせる方法も検討の余地があります。
例:商品一覧の「絞り込み」ボタンで1回通す
ここからは、架空の商品一覧ページで手順を1回通します。数値は説明用の例です。
ステップ1〜2。Search Console で、商品一覧のテンプレートを使う URL のグループが「INP 改善が必要」になっていたとします。このページで押される操作は、カテゴリの絞り込みチェックボックス、並び替え、ページ送り、カートに入れるボタンの4つです。RUM はないので、4つを全部試すことにします。
ステップ3。CPU を遅くした状態でパフォーマンスパネルを記録し、4つの操作を順に押します。並び替えとページ送りは軽い。絞り込みのチェックボックスだけ、押してからチェックが付くまでに体感で引っかかりがあります。
ステップ4。記録上の絞り込み操作を分けると、たとえば次のような内訳だったとします。
- ①入力の遅延:40ミリ秒
- ②処理時間:260ミリ秒
- ③表示の遅延:50ミリ秒
- 合計:350ミリ秒(「改善が必要」の範囲)
処理時間の中を開くと、クリックのイベント処理が1本の長いタスクになっていました。中身は「チェック状態の更新 → 全商品データの絞り込み計算 → 一覧の再描画 → 件数表示の更新 → 計測タグへの送信」です。
ステップ5。いちばん長いのは②なので、ここを分割します。方針は「利用者が押した結果として真っ先に見たいものだけを先に出す」です。
filterCheckbox.addEventListener('click', (event) => {
// 押した直後に見える変化だけを先に出す
markChecked(event.target);
showLoadingState();
// 残りは次のフレーム以降の別タスクへ
requestAnimationFrame(() => {
setTimeout(() => {
const items = applyFilter(allItems, getSelectedFilters());
renderList(items);
updateCount(items.length);
sendAnalytics('filter', getSelectedFilters());
});
});
});
requestAnimationFrame の中で setTimeout を呼ぶ形は、web.dev の最適化ガイドが文字入力の例で示している書き方と同じ考え方です。見える更新を先に描かせ、残りを次のフレーム以降のタスクに回します。
分割後、チェックが付いて「絞り込み中」の表示が出るまでの処理は軽くなります。そのぶん INP として測られる区間は短くなります。ただし、後ろに回した一覧の再描画そのものが重いままなら、利用者は結局待たされます。次の一手として、絞り込み計算を事前に索引化する、一覧の件数を減らして描画量を下げる、といった③側の対策も並行して検討します。
ステップ6。デプロイ後、Search Console のグループの判定を見続けます。判定が変わらない場合は、別の操作(たとえば「カートに入れる」ボタン)が最も遅い操作として残っている可能性があります。INP はページで最も遅い操作で決まるので、1つ直すと次に遅い操作が表に出てくることがあります。
さきほどの表と照らすと、この例は②の典型でした。「全部をクリックの中でやる」実装は、一覧系・フォーム系のページで特に起こりやすい形です。
直す前の自己点検
手を動かす前に、次の項目を自分のページに当てはめてください。
| 確認項目 | はい | いいえ |
|---|---|---|
| 判定は実ユーザーのデータ(CrUX / Search Console)で見たか | ステップ2へ | ラボの数値だけで判断しない。現場データを先に見る |
| 遅い操作を1つ名指しできるか | ステップ3へ | 候補の操作を列挙し、1つずつ記録する |
| 疑っている遅さはスクロールやズームではないか | 押す・打つ操作を調べる | INP の対象外。別の問題として扱う |
| 3区間のうち最長の区間が分かっているか | その区間の打ち手から着手 | パフォーマンスパネルで内訳を確認する |
| 直した操作のあとに、次に遅い操作がないか | 監視を続ける | 次の候補を同じ手順で調べる |
順位のために INP を直すべきか
Google 検索セントラルは、良好なコアウェブバイタルの達成を勧めたうえで、それがほかのページ体験の要素とともに、コアランキングシステムが評価しようとしているものと一致する、と説明しています。言い方は「一致する」であって、INP を直せば順位が上がると約束するものではありません。
そのため、INP の改善は「操作したのに反応しない」という利用者の不満を減らす施策として位置づけるのが現実的です。順位への期待をどこまで持つべきかは、ページ速度を改善しても順位が変わらない理由で整理しています。INP 以外の指標も含めてレポートの悪化を切り分けたい場合は、先にコアウェブバイタル悪化を切り分ける5つの手順で、どの指標がどれだけ目安から離れているかを確かめてから、この記事の手順に進んでください。
出典
