ラボでやり取りが遅い場合を手動で診断する

フィールド データをラボに取り込んで、手動テストで遅いインタラクションの原因を再現し、特定する方法を学習します。

Interaction to Next Paint(INP)の最適化で難しい部分は、INP が低い原因を突き止めることです。メインスレッドで多くのタスクをスケジュールするサードパーティのスクリプト、大きな DOM サイズ、負荷の高いイベント コールバックなど、さまざまな原因が考えられます。

低い INP を修正する方法を見つけるのは難しい場合があります。まず、ページの INP に寄与している可能性が高いインタラクションを把握する必要があります。実際のユーザーから見て、ウェブサイト上のどのインタラクションが最も遅くなる傾向があるかわからない場合は、まずフィールドで遅いインタラクションを見つけるをご覧ください。フィールド データが得られたら、ラボツールでそれらの特定のインタラクションを手動でテストし、それらのインタラクションが遅い理由を突き止めることができます。

フィールド データがない場合はどうすればよいでしょうか。

フィールド データを用意することは、最適化が必要なインタラクションを見つけるのに要する時間を大幅に節約できるため、非常に重要です。しかし、フィールド データがない状況にいるかもしれません。これが現在の状況に当てはまる場合、多少の労力と別のアプローチが必要になりますが、改善するインタラクションを見つけることは可能です。

Total Blocking Time(TBT)は、読み込み中のページの応答性を評価するラボ指標であり、INP と非常によく相関しています。ページの TBT が高い場合、最初のページ読み込み時にページがユーザーの操作にあまり反応していない可能性があります。

ページの TBT を把握するには、Lighthouse または PageSpeed Insights を使用します。ページの TBT が「良好」しきい値を満たしていない場合は、ページの読み込み中にメインスレッドがビジー状態になる可能性が高いため、ページのライフサイクルで重要なタイミングでインタラクションが発生するまでの時間に影響が及ぶ可能性があります。

ページの読み込み後に遅いインタラクションを見つけるには、ウェブサイトのアナリティクスですでに特定されている一般的なユーザーフローなど、他の種類のデータを利用する必要があります。たとえば、e コマース ウェブサイトを扱っている場合、ユーザーがオンライン ショッピング カートに商品を追加し、その後の購入手続きを行う際に行うアクションは、一般的なユーザーフローになります。

フィールド データの有無にかかわらず、次のステップは遅いインタラクションを手動でテストして再現することです。これは、遅いインタラクションを修正できると判断できる場合に限られます。

ラボで遅いインタラクションを再現する

ラボでは、手動テストによって遅いインタラクションを再現する方法はいろいろありますが、以下に、ラボ環境で認知の労力を最小限に抑えながら遅いインタラクションを再現するためのフレームワークを示します。

すぐにパフォーマンス プロファイラにアクセスしない

Chrome のパフォーマンス プロファイラを使い慣れている方であれば、ページのパフォーマンスに関する問題のトラブルシューティングを行う際に、多くの有用な診断情報が得られることをご存じでしょう。このツールには多くの長所があります。

ただし、Chrome のパフォーマンス プロファイラでは、ページの操作中にライブビューが提供されないという欠点があります。使用するには時間がかかります。また、最初にインタラクションを手動でテストする効率的な方法があります。低速なインタラクションを再現するために最小限の時間と労力を費やし、低速なインタラクションが最終的に特定されたら、パフォーマンス プロファイラを使用してその背後にある原因を深く掘り下げます。

Chrome 拡張機能の Web Vitals を使用する

Web Vitals Chrome 拡張機能を使用すると、最小限の労力で操作のレイテンシを手動でテストできます。この拡張機能をインストールすると、DevTools コンソールにインタラクション データが表示されます。ただし、最初に次の操作を行う必要があります。

  1. Chrome で、アドレスバーの右にある拡張機能アイコンをクリックします。
  2. プルダウン メニューで [Web Vitals] 拡張機能を見つけます。
  3. 右側のアイコンをクリックして拡張機能の設定を開きます。
  4. [オプション] をクリックします。
  5. 表示される画面で [コンソール ロギング] チェックボックスをオンにして、[保存] をクリックします。

完了したら、Chrome DevTools でコンソールを開き、ウェブサイトでの疑わしいインタラクションのテストを開始します。ページを操作すると、有用な診断データがコンソールに表示されます。

Web Vitals 拡張機能がインタラクションについて提供するコンソール ロギングのスクリーンショット。このロギングには、タイミングやその他のコンテキスト情報などの詳細が含まれます。
コンソール ロギングが有効になっている場合の Web Vitals 拡張機能のコンソール エントリ。対象となるインタラクションごとに、インタラクション データがコンソールに記録されます。

JavaScript スニペットを使用する

Web Vitals 拡張機能は、有用であるとしても、すべてのユーザーにとって有効なオプションであるとは限りません。デバイスのセキュリティ ポリシーにより、環境によってはブラウザ拡張機能がブロックされることがあります。また、拡張機能をモバイル デバイスにインストールすることもできません。後者の場合、Android 搭載の物理デバイスでリモート デバッグを使用して手動でテストする場合は、問題が発生します。

Web Vital 拡張機能を使用する別の方法として、JavaScript をコピーして DevTools コンソールに貼り付けることもできます。次のコードは、すべてのインタラクションで Web Vitals 拡張機能と同じコンソール出力を提供します。

let worstInp = 0;

const observer = new PerformanceObserver((list, obs, options) => {
  for (let entry of list.getEntries()) {
    if (!entry.interactionId) continue;

    entry.renderTime = entry.startTime + entry.duration;
    worstInp = Math.max(entry.duration, worstInp);

    console.log('[Interaction]', entry.duration, `type: ${entry.name} interactionCount: ${performance.interactionCount}, worstInp: ${worstInp}`, entry, options);
  }
});

observer.observe({
  type: 'event',
  durationThreshold: 0, // 16 minimum by spec
  buffered: true
});

インタラクションが確実に遅いと判断したら、パフォーマンス プロファイラでインタラクションをプロファイリングして、遅い理由に関する詳細情報を取得できます。

遅いインタラクションを再現できない場合はどうすればよいですか?

フィールド データから特定の操作が遅いことが示されているが、ラボで問題を手動で再現できない場合はどうすればよいでしょうか。この原因としてはいくつかの理由が考えられますが、これは、あらゆる種類のパフォーマンスの問題のトラブルシューティングにおいてよくある課題です。

一旦インタラクションをテストする際の状況は、使用しているハードウェアとネットワーク接続によって異なります。結局のところ、高速接続で高速なデバイスを使用しているかもしれませんが、だからといってユーザーが幸運であるとは限りません。この状況が当てはまる場合は、次の 3 つのいずれかの対応が可能です。

  1. Android 搭載デバイスの実機をお持ちの場合は、リモート デバッグを使用して、ホストマシンで Chrome DevTools インスタンスを開き、そこで遅いインタラクションを再現してみます。モバイル デバイスはノートパソコンやデスクトップ マシンほど高速でないことが多く、このような状況ではインタラクションが遅くなりがちです。
  2. 実機がない場合は、Chrome DevTools で CPU スロットリング機能を有効にします
  3. ステップ 1 と 2 の両方を同時に試してください。Android 搭載の物理デバイスの DevTools インスタンスで CPU スロットリングを有効にすることもできます。

もう 1 つの原因としては、ページの読み込みを待ってから操作を行っているのに、ユーザーがまだその操作を完了していないことが考えられます。高速のネットワークを使用している場合は、ネットワーク スロットリングを有効にして低速のネットワーク状態をシミュレートし、ペイント後すぐにページを操作します。メインスレッドは起動時に最もビジー状態になることが多いため、このようにする必要があります。

トレースを記録する

インタラクションが遅い理由を詳しく把握するには、次のステップとして Chrome DevTools のパフォーマンス プロファイラを使用します。Chrome のパフォーマンス プロファイラでインタラクションをプロファイリングする手順は次のとおりです。

  1. テスト対象のページを開きます。
  2. Chrome DevTools を開き、[パフォーマンス] パネルに移動します。
  3. パネルの左上にある [Record] ボタンをクリックしてトレースを開始します。
  4. プロファイリングするインタラクションを実行します。
  5. もう一度 [Record] ボタンをクリックしてトレースを停止します。

プロファイラにデータが入力されると、最初に確認されるのはプロファイラの上部にあるアクティビティの概要です。アクティビティの概要では、記録中に長時間タスクが発生した場所に赤いバーが表示されます。これにより、問題領域をすばやく拡大できます。

Chrome DevTools のパフォーマンス パネルにあるアクティビティの概要のスクリーンショット。表示されるアクティビティのほとんどは、フレーム チャートの上の赤色でハイライトされた長いタスクを発生させる JavaScript からのものです。
Chrome のパフォーマンス プロファイラの上部にあるアクティビティの概要です。長いタスクは、アクティビティのフレームチャートの上に赤色でハイライト表示されます。この場合、長いタスクの作業の大部分を、スクリプト作成のかなりの作業が占めていました。

アクティビティの概要で領域をドラッグして選択することで、問題のある領域をすばやく確認できます。インタラクションが発生した場所に焦点を当てたら、[Interactions] トラックを使用すると、インタラクションとその下のメインスレッド トラックで発生したアクティビティを並べることができます。

Chrome DevTools のパフォーマンス パネルに表示された操作のスクリーンショット。メインスレッド トラックの上にあるインタラクション トラックには、メインスレッド アクティビティと並んでインタラクションの継続時間が表示されます。
Chrome の DevTools のパフォーマンス プロファイラでプロファイリングされたインタラクション。 [Interactions] トラックには、クリック インタラクションに対応する一連のイベントが表示されます。Interactions のトラック エントリは、その操作を引き起こしたタスクにまたがっています。

ここからは、遅いインタラクションの原因となっている問題を深く掘り下げます。インタラクションのレイテンシが高くなる原因は多数ありますが、その一部についてはこのガイドで詳しく説明します。

トレースの代わりに Lighthouse の期間を使用する

Chrome のパフォーマンス プロファイラにはさまざまな診断情報が備わっていますが、初心者には不安を感じるかもしれません。パフォーマンスプロファイラの代わりに Lighthouse のタイムスパンモードを使用できますこのモードを使用する手順は次のとおりです。

  1. DevTools を開いて、DevTools の [Lighthouse] タブに移動します。
  2. [モード] で [期間] オプションを選択します。
  3. [デバイス] というラベルの付いたセクションで、[デスクトップ] または [モバイル] のデバイスタイプを選択します。
  4. 少なくとも [カテゴリ] ラベルの下の [パフォーマンス] チェックボックスがオンになっていることを確認します。
  5. [期間を開始] ボタンをクリックします。
  6. データを取得するページでインタラクションをテストします。
  7. [期間を終了] ボタンをクリックし、監査が表示されるまで待ちます。
  8. [Lighthouse] タブに監査が入力されたら、[Show audits related to] ラベルの横にある [INP] リンクをクリックして、監査を INP でフィルタします。

この時点で、不合格または合格した監査のプルダウン リストが表示されます。プルダウンを開くと、インタラクション中に費やした時間の内訳が表示されます。

タイムスパン モードで表示された Lighthouse の監査のスクリーンショット。この監査は INP に固有のもので、インタラクションをトリガーした要素のスクリーンショットや、インタラクションの処理に費やした時間の詳細を示す表など、インタラクションの詳細が表示されます。
Lighthouse の期間モードでプロファイリングされたインタラクション。Lighthouse では、ページに対する操作が行われると、操作中に費やされた時間を監査して、入力遅延、処理遅延、表示遅延に分類できます。

長い入力遅延を特定する方法

インタラクション レイテンシが高くなる原因の一つに、入力遅延があります。 入力遅延は、インタラクションの最初の段階です。これは、オペレーティング システムがユーザー アクションを最初に受信してから、その入力によってトリガーされた最初のイベントの処理をブラウザが開始できるまでの時間です。入力遅延は、インタラクションのイベント コールバックの実行が開始されるタイミングで終了します。

Chrome のパフォーマンス プロファイラで入力遅延を特定するには、インタラクション トラックでインタラクションの開始位置を特定し、そのインタラクションのイベント コールバックの実行開始位置を特定します。

オペレーティング システムが入力イベントをブラウザに渡すには時間がかかるため、ある程度の入力遅延は常に予想する必要があります。ただし、入力遅延の長さはある程度制御できます。重要なのは、コールバックの実行を妨げている作業がメインスレッドで実行されているかどうかを確認することです。

Chrome のパフォーマンス パネルに表示された入力遅延の図。サードパーティ スクリプトからのタイマー起動によって入力遅延が増加するため、インタラクションの開始はイベントのコールバックのかなり前に発生します。
サードパーティのスクリプトからタイマーによって起動されたタスクが原因で発生する入力遅延。

上の図では、ユーザーがページを操作しようとしたときにサードパーティのスクリプトのタスクが実行されているため、入力遅延が長くなります。長い入力遅延はインタラクションのレイテンシに影響するため、ページの INP に影響する可能性があります。

コストの高いイベント コールバックを特定する方法

イベント コールバックは、入力遅延の直後に実行されます。イベント コールバックの実行時間が長すぎると、ブラウザでの次のフレームの表示が遅れ、操作の合計レイテンシが大幅に増加する可能性があります。長時間実行されるイベント コールバックは、計算コストの高いファースト パーティまたはサードパーティの JavaScript が原因である可能性があります。場合によっては、その両方が原因です。

Chrome のパフォーマンス パネルに表示されたイベント コールバック タスクの画像。このイベントのコールバックは、長いタスクで発生するポインタダウン イベントとクリック イベントに対して発生します。
Chrome DevTools のパフォーマンス プロファイラに表示される、クリック操作に応答して実行されるイベント コールバック。[Event: pointdown] エントリと [Event: click] エントリの右上には、コストの高いイベントのコールバックを示す赤い三角形があります。

コストの高いイベント コールバックを見つけるには、特定の操作のトレースで以下を確認します。

  1. イベント コールバックに関連付けられたタスクが長時間のタスクかどうかを判断します。ラボの設定で時間のかかるタスクをより確実に確認するには、パフォーマンス パネルで CPU スロットリングを有効にするか、低~中間階層の Android 搭載デバイスを接続してリモート デバッグを使用する必要があります。
  2. イベント コールバックを実行するタスクが長いタスクの場合は、コールスタックでエントリの右上に赤い三角形が表示されているイベント ハンドラのエントリ(Event: click などの名前を含むエントリなど)を探します。これらは高コストなイベント コールバックです。

コストの高いイベント コールバックに対処するには、次のいずれかの方法を試してください。

  1. 最小限の作業に:高コストなイベントコールバックで発生する すべての処理が厳密に必要なのか存在しない場合は、可能であればそのコードを完全に削除するか、削除できない場合は後で実行を延期することを検討してください。また、フレームワーク機能を利用することもできます。たとえば、React の PureComponent クラスメモ化機能では、コンポーネントの小道や状態が変更されていない場合、不要なレンダリング作業をスキップできます。
  2. イベント コールバックの非レンダリング処理を後で延期する。長いタスクは、メインスレッドに譲ることで分割できます。メインスレッドに放棄するたびに、現在のタスクの実行が終了し、残りの作業が別のタスクに分割されます。これにより、イベント コールバックで前に実行されたユーザー インターフェースの更新をレンダラが処理できるようになります。React を使用している場合は、遷移機能がこの処理を自動的に行うことができます。

この方法を採用すると、ユーザー入力にすばやく応答する場所にイベント コールバックを取得できるようになります。

プレゼンテーションの遅延を特定する方法

長い入力遅延と高コストなイベント コールバックだけが、INP の低下の原因となる可能性があります。イベント コールバック コードが少量でも、レンダリングの更新が高コストになることがあります。インタラクションの結果を反映するために、ブラウザがユーザー インターフェースの視覚的な更新をレンダリングするのにかかる時間を、表示遅延といいます。

Chrome DevTools のパフォーマンス パネルで可視化された作業のレンダリング。レンダリング処理は、次のフレームを描画するために、イベント コールバックの後に行われます。
Chrome のパフォーマンス プロファイラに表示されるタスクをレンダリングします。レンダリング処理は紫色で、ペイント処理は緑色で示されています。

インタラクション レイテンシが高くなるすべての原因の中で、レンダリング作業のトラブルシューティングと修正が最も難しい場合がありますが、その労力には価値があります。過剰なレンダリング処理は、次のいずれかが原因で発生する可能性があります。

  • 大きな DOM サイズ。ページのプレゼンテーションの更新に必要なレンダリング作業は、多くの場合、ページの DOM のサイズが大きくなると増加します。詳しくは、DOM サイズを大きくした場合のインタラクティビティへの影響と対処方法をご覧ください。
  • 強制リフロー。これは、JavaScript で要素にスタイルの変更を適用し、その処理の結果をクエリするときに発生します。その結果、ブラウザは他の処理を行う前にレイアウト作業を実行しなければならず、ブラウザは更新されたスタイルを返すことができます。強制的なリフローを回避するための詳細とヒントについては、大規模で複雑なレイアウトとレイアウト スラッシングを回避するをご覧ください。
  • requestAnimationFrame コールバックでの過剰または不要な処理。requestAnimationFrame() コールバックは、イベントループのレンダリング フェーズで実行されます。このコールバックは、次のフレームが表示される前に完了する必要があります。requestAnimationFrame() を使用して、ユーザー インターフェースの変更を伴わない処理を行っている場合は、次のフレームが遅延する可能性があることを理解してください。
  • ResizeObserver コールバック。このようなコールバックはレンダリングの前に実行され、その処理にコストがかかる場合は次のフレームの表示が遅れる可能性があります。イベント コールバックと同様に、次のフレームで不要なロジックは先送りします。

INP のトラブルシューティングは反復プロセスである

INP の低下の原因となっているインタラクション レイテンシが高い原因を特定するには多大な労力がかかりますが、原因を突き止めることができれば、半分終わりました。INP の低さをトラブルシューティングするための系統的なアプローチに従うことで、問題の原因を確実に特定し、適切な修正に迅速に到達できます。確認方法:

最後のものは最も重要なものです。ページ パフォーマンスを改善するために行う他のほとんどの作業と同様に、INP のトラブルシューティングと改善は周期的なプロセスです。遅いインタラクションを 1 つ修正して次のインタラクションに進み、結果が表示されるまで繰り返します。油断しないで!