ウェブサイトの Interaction to Next Paint を最適化する方法について説明します。
公開日: 2023 年 5 月 19 日、最終更新日: 2025 年 9 月 9 日
Interaction to Next Paint(INP)は、安定版のウェブに関する主な指標で、ユーザーがページにアクセスしている全期間中に発生するすべての対象となるインタラクションのレイテンシをモニタリングすることで、ユーザー インタラクションに対するページの全体的な応答性を評価します。最終的な INP 値は、最大時間を要したことがモニタリングされたインタラクションです(外れ値は無視されることがあります)。
優れたユーザー エクスペリエンスを提供するには、ウェブサイトで Interaction to Next Paint を 200 ミリ秒以下に収めるようにします。ほとんどのユーザーが閲覧する際に目標値が達成されるよう、モバイル デバイスとデスクトップ デバイスでセグメント化したページ読み込みの 75 パーセンタイルを測定するしきい値として使用することをおすすめします。
ウェブサイトによっては、インタラクティブな要素がほとんどないテキストと画像が中心のページなど、インタラクションがほとんどない場合やまったくない場合があります。テキスト エディタやゲームなどのウェブサイトの場合、数百、数千ものインタラクションが発生する可能性があります。いずれにしても、INP が高い場合はユーザー エクスペリエンスが損なわれる可能性があります。
INP の改善には時間と労力がかかりますが、ユーザー エクスペリエンスの向上というメリットがあります。このガイドでは、INP を改善するための方法について説明します。
INP が低い原因を特定する
インタラクションの遅延を修正するには、まずウェブサイトの INP が低いのか、改善が必要なのかを判断するためのデータが必要です。この情報を入手したら、ラボに移動して遅いインタラクションの診断を開始し、解決策を見つけます。
フィールドで遅いインタラクションを見つける
理想的には、INP の最適化はフィールド データから始めるのが望ましいです。リアルユーザー モニタリング(RUM)プロバイダのフィールド データは、ページの INP 値だけでなく、INP 値の原因となった特定のインタラクション、インタラクションがページ読み込み中または読み込み後に発生したかどうか、インタラクションのタイプ(クリック、キープレス、タップ)などのコンテキスト データも提供します。
RUM プロバイダに依存せずにフィールド データを取得する場合は、INP フィールド データガイドで、PageSpeed Insights を使用して Chrome ユーザー エクスペリエンス レポート(CrUX)のデータを表示することを推奨しています。CrUX は Core Web Vitals プログラムの公式データセットであり、INP を含む数百万ものウェブサイトの指標の概要を提供します。ただし、CrUX では、RUM プロバイダから取得できるような、問題の分析に役立つコンテキスト データが提供されないことがよくあります。そのため、可能な場合は RUM プロバイダを使用するか、独自の RUM ソリューションを実装して CrUX で利用できるデータを補完することをおすすめします。
ラボで遅いインタラクションを診断する
理想的には、インタラクションが遅いことを示すフィールド データが得られたら、ラボでテストを開始します。フィールド データがない場合は、ラボで遅いインタラクションを特定するための戦略がいくつかあります。一般的なユーザーフローに沿ってテストを行い、その過程でインタラクションをテストする戦略や、読み込み中にページを操作する戦略(メインスレッドが最もビジー状態になることが多い)などがあります。これにより、ユーザー エクスペリエンスの重要な部分で遅いインタラクションを特定できます。
インタラクションを最適化する
遅いインタラクションを特定し、ラボで手動で再現できるようになったら、次のステップは最適化です。
インタラクションは次の 3 つの部分に分類できます。
- 入力遅延。ユーザーがページとのインタラクションを開始したときに始まり、インタラクションのイベント コールバックの実行が開始されたときに終わります。
- 処理時間。イベント コールバックが完了するまでの時間で構成されます。
- プレゼンテーション遅延。ブラウザがインタラクションの視覚的な結果を含む次のフレームを表示するのにかかる時間。
これら 3 つのサブパートの合計が、インタラクションの合計レイテンシになります。インタラクションのすべてのサブパートは、インタラクションの合計レイテンシに一定の時間を費やします。そのため、インタラクションの各パートをできるだけ短い時間で実行できるように最適化する方法を知ることが重要です。
入力遅延を特定して軽減する
ユーザーがページを操作したとき、その操作の最初の部分は入力遅延です。ページの他のアクティビティによっては、入力遅延が長くなることがあります。これは、メインスレッドでアクティビティが発生した(スクリプトの読み込み、解析、コンパイルなどが原因である可能性があります)、フェッチ処理、タイマー関数、または連続して発生し、互いに重複する他のインタラクションが原因である可能性があります。
インタラクションの入力遅延の原因が何であれ、インタラクションがイベント コールバックをできるだけ早く実行できるように、入力遅延を最小限に抑える必要があります。
起動時のスクリプト評価と長時間タスクの関係
ページのライフサイクルにおけるインタラクティブ性の重要な側面は、起動時です。ページが読み込まれると、最初はレンダリングされますが、ページがレンダリングされたからといって、ページの読み込みが完了したとは限りません。ページが完全に機能するために必要なリソースの数によっては、読み込み中にユーザーがページを操作しようとする可能性があります。
ページの読み込み中にインタラクションの入力遅延を長くする原因の一つに、スクリプトの評価があります。JavaScript ファイルがネットワークから取得された後も、ブラウザは JavaScript を実行する前に処理を行う必要があります。この処理には、スクリプトを解析して構文が有効かどうかを確認し、バイトコードにコンパイルしてから、最終的に実行することが含まれます。
スクリプトのサイズによっては、この処理によってメインスレッドで長時間実行タスクが発生し、ブラウザが他のユーザー操作に応答するまでの時間が長くなる可能性があります。ページ読み込み中にユーザー入力に対してページが応答性を維持するには、ページ読み込み中に長いタスクが発生する可能性を減らして、ページが応答性を維持できるようにすることが重要です。
イベント コールバックを最適化する
入力遅延は、INP が測定するものの最初の部分にすぎません。また、ユーザー操作に応じて実行されるイベント コールバックをできるだけ早く完了できるようにする必要があります。
メインスレッドに頻繁に譲る
イベント コールバックを最適化するうえで最も一般的なアドバイスは、コールバック内でできるだけ処理を行わないことです。ただし、インタラクション ロジックが複雑な場合、ユーザーの作業をわずかにしか削減できないことがあります。
ウェブサイトでこの問題が発生している場合は、イベント コールバックの処理を個別のタスクに分割してみてください。これにより、メインスレッドをブロックする長時間タスクになるのを防ぎ、メインスレッドで待機していた他のインタラクションをより早く実行できるようになります。
setTimeout
は、タスクを分割する 1 つの方法です。これは、渡されたコールバックが新しいタスクで実行されるためです。setTimeout
を単独で使用することも、より人間工学的なイールドのために、その使用を別の関数に抽象化することもできます。
無差別に yield するのは、まったく yield しないよりはましですが、メインスレッドに yield するには、より微妙な方法があります。それは、ユーザー インターフェースを更新するイベント コールバックの直後にのみ yield して、レンダリング ロジックをより早く実行できるようにする方法です。
レンダリング作業を早めに実行できるようにする
より高度なイールド手法では、イベント コールバックのコードを構造化して、実行される処理を次のフレームのビジュアル アップデートの適用に必要なロジックのみに制限します。それ以外のことは、後続のタスクに延期できます。これにより、コールバックが軽量で機敏になるだけでなく、イベント コールバック コードでビジュアル アップデートがブロックされないため、インタラクションのレンダリング時間も短縮されます。
たとえば、入力したテキストを書式設定するリッチテキスト エディタで、入力した内容に応じて UI の他の要素(単語数、スペルミスをハイライト表示するなど)も更新されるとします。また、アプリは、ユーザーが離席して戻ってきたときに作業が失われないように、ユーザーが書いた内容を保存する必要がある場合もあります。
この例では、ユーザーが入力した文字に応じて、次の 4 つの処理を行う必要があります。ただし、次のフレームが表示される前に完了する必要があるのは最初の項目のみです。
- ユーザーが入力した内容でテキスト ボックスを更新し、必要な書式設定を適用します。
- 現在の単語数を表示する UI の部分を更新します。
- スペルミスを確認するロジックを実行します。
- 最新の変更を保存します(ローカルまたはリモート データベース)。
このコードは次のようになります。
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
次の可視化は、重要でない更新を次のフレームまで延期することで、処理時間を短縮し、全体的なインタラクション レイテンシを短縮できることを示しています。

前のコード例で requestAnimationFrame()
呼び出し内で setTimeout()
を使用するのは、確かに少し難解ですが、すべてのブラウザで動作する効果的な方法であり、重要でないコードが次のフレームをブロックするのを防ぎます。
レイアウト スラッシングを回避する
レイアウト スラッシング(強制同期レイアウトとも呼ばれます)は、レイアウトが同期的に発生するレンダリング パフォーマンスの問題です。これは、JavaScript でスタイルを更新してから、同じタスクでスタイルを読み取るときに発生します。JavaScript には、レイアウト スラッシングを引き起こす可能性のあるプロパティが多数あります。
![Chrome DevTools の [パフォーマンス] パネルに表示されるレイアウト スラッシングの可視化。](https://web.dev/static/articles/optimize-inp/image/a-visualization-layout-t-cefcc10055727.png?authuser=0000&hl=ja)
レイアウト スラッシングは、パフォーマンスのボトルネックになります。スタイルを更新してから、JavaScript でそれらのスタイルの値をすぐにリクエストすると、ブラウザは同期レイアウト作業を強制的に実行することになります。本来であれば、イベント コールバックの実行が完了した後に非同期で実行できるはずです。
表示の遅延を最小限に抑える
インタラクションの表示遅延は、インタラクションのイベント コールバックの実行が完了してから、ブラウザが結果の視覚的な変化を示す次のフレームを描画できる時点までの期間を示します。
DOM サイズを最小限に抑える
ページの DOM が小さい場合、通常はレンダリング作業がすぐに完了します。ただし、DOM が非常に大きくなると、レンダリング作業は DOM サイズの増加とともに拡大する傾向があります。レンダリング作業と DOM サイズの関係は線形ではありませんが、大きな DOM は小さな DOM よりもレンダリングに多くの作業を必要とします。大規模な DOM は、次の 2 つのケースで問題になります。
- 初期ページのレンダリング時。大きな DOM では、ページの初期状態をレンダリングするのに多くの作業が必要になります。
- ユーザー操作に対する応答。DOM サイズが大きいと、レンダリングの更新にコストがかかり、ブラウザが次のフレームを表示するまでの時間が長くなる可能性があります。
大規模な DOM を大幅に削減できない場合があることに注意してください。DOM サイズを小さく保つために、DOM をフラット化する、ユーザー操作中に DOM に追加するなどの方法で DOM サイズを小さくできますが、これらの手法には限界があります。
content-visibility
を使用して画面外の要素を遅延レンダリングする
ページの読み込み時のレンダリング作業とユーザー操作に応じたレンダリング作業の両方を制限する方法の 1 つは、CSS の content-visibility
プロパティを使用することです。これは、要素がビューポートに近づくにつれて遅延レンダリングを行うのと同等です。content-visibility
を効果的に使用するにはある程度の練習が必要ですが、ページの INP を改善できるレンダリング時間の短縮につながるかどうかを検討する価値はあります。
JavaScript を使用して HTML をレンダリングする際のパフォーマンス コストに注意する
HTML があるところには HTML 解析があり、ブラウザが HTML を DOM に解析し終えたら、スタイルを適用し、レイアウトの計算を行い、そのレイアウトをレンダリングする必要があります。これは避けられないコストですが、HTML のレンダリング方法が重要になります。
サーバーから HTML が送信されると、ブラウザにストリームとして届きます。ストリーミングとは、サーバーからの HTML レスポンスがチャンク単位で届くことを意味します。ブラウザは、ストリームのチャンクが到着するたびに増分解析し、ビットごとにレンダリングすることで、ストリームの処理方法を最適化します。これは、ブラウザがページ読み込み中に定期的に自動で暗黙的にイールドするため、無料で利用できるパフォーマンスの最適化です。
どのウェブサイトへの初回アクセスでも、必ずある程度の HTML が使用されますが、一般的なアプローチでは、最小限の初期 HTML から始まり、JavaScript を使用してコンテンツ領域にデータを入力します。そのコンテンツ領域のその後の更新も、ユーザー操作の結果として行われます。これは通常、シングルページ アプリケーション(SPA)モデルと呼ばれます。このパターンの欠点の 1 つは、クライアントで JavaScript を使用して HTML をレンダリングすると、その HTML を作成するための JavaScript 処理のコストだけでなく、ブラウザがその HTML の解析とレンダリングを完了するまで処理を譲らないことです。
ただし、SPA ではないウェブサイトでも、インタラクションの結果として JavaScript を介した HTML レンダリングが多少は行われる可能性が高いことを覚えておくことが重要です。一般的には問題ありませんが、クライアントで大量の HTML をレンダリングすると、次のフレームの表示が遅れる可能性があります。ただし、このアプローチでブラウザに HTML をレンダリングすると、パフォーマンスにどのような影響があるか、また、JavaScript を使用して大量の HTML をレンダリングする場合に、ユーザー入力に対するウェブサイトの応答性にどのような影響があるかを理解しておくことが重要です。
まとめ
サイトの INP を改善するには、反復的なプロセスが必要です。フィールドで遅いインタラクションを修正すると、特にウェブサイトで多くのインタラクティブ機能が提供されている場合は、他の遅いインタラクションが見つかり、それらも最適化する必要がある可能性が高くなります。
INP を改善する鍵は、粘り強さです。時間をかけて、ユーザーが満足するようなレスポンシブなページにすることができます。ユーザー向けの新機能を開発する際に、ユーザー固有のインタラクションを最適化する同じプロセスが必要になる可能性もあります。時間と労力はかかりますが、それに見合うだけの価値はあります。
ヒーロー画像は Unsplash の David Pisnoy 氏によるもので、Unsplash ライセンスに基づいて変更されています。