入力遅延とは何か、入力遅延を減らしてインタラクティブ性を高める方法について説明します。
ウェブ上のインタラクションは複雑で、ブラウザ内でさまざまなアクティビティが発生してインタラクションが駆動されます。ただし、イベント コールバックの実行が開始される前に、入力遅延が発生するという共通点があります。このガイドでは、入力遅延とは何か、ウェブサイトのインタラクションを高速化するために入力遅延を最小限に抑える方法について説明します。
入力遅延とは何ですか?
入力遅延とは、ユーザーが最初にページを操作したとき(画面のタップ、マウスのクリック、キーの押下など)から、その操作のイベント コールバックが実行されるまでの期間です。すべてのインタラクションは、ある程度の入力遅延から始まります。
入力遅延の一部は避けられません。オペレーティング システムが入力イベントを認識してブラウザに渡すには、常に一定の時間がかかります。ただし、入力遅延のその部分はほとんど気づかないことが多く、ページ自体で発生する他のことが原因で入力遅延が長くなり、問題が発生することがあります。
入力遅延の考え方
一般的に、ユーザーのデバイスに関係なく、ウェブサイトが Interaction to Next Paint(INP)指標の「良好」のしきい値を満たす可能性を最大限に高めるには、インタラクションのすべての部分をできるだけ短くする必要があります。入力遅延を抑えることは、そのしきい値を満たすための 1 つの要素にすぎません。
そのため、INP の「良好」のしきい値を満たすために、可能な限り短い入力遅延を目指す必要があります。ただし、入力遅延を完全に解消することはできません。ユーザーがページを操作しようとしているときに、メインスレッドでの過剰な作業を避けていれば、入力遅延は問題が起こらない程度に低くなります。
入力遅延を最小限に抑える方法
前述のとおり、入力遅延は避けられないものもありますが、避けられるものもあります。入力の遅延が長い場合は、次の点を考慮してください。
メインスレッドで過剰な処理を開始する繰り返しタイマーを回避する
JavaScript には、入力遅延の原因となる setTimeout と setInterval の 2 つのタイマー関数がよく使用されます。2 つの違いは、setTimeout が指定された時間の後に実行されるコールバックをスケジュールすることです。一方、setInterval は、n ミリ秒ごとにコールバックを永続的に実行するようにスケジュールします。または、clearInterval でタイマーが停止するまで実行します。
setTimeout 自体は問題ではありません。実際、長いタスクを回避するのに役立ちます。ただし、タイムアウトが発生したタイミングと、タイムアウト コールバックの実行中にユーザーがページを操作しようとしたかどうかによって異なります。
また、setTimeout はループまたは再帰的に実行できます。この場合、setInterval のように動作しますが、前のイテレーションが完了するまで次のイテレーションをスケジュールしないことが望ましいです。つまり、setTimeout が呼び出されるたびにループがメインスレッドに処理を譲ることになりますが、コールバックが過剰な処理を行わないように注意する必要があります。
setInterval は一定の間隔でコールバックを実行するため、インタラクションの妨げになる可能性がはるかに高くなります。これは、setTimeout 呼び出しの単一インスタンスはユーザー操作の妨げになる可能性がある 1 回限りのコールバックであるのに対し、setInterval は繰り返し発生するため、操作の妨げになる可能性がはるかに高く、操作の入力遅延が増加するためです。
setInterval 呼び出しによって登録されたタイマー。入力遅延が追加されると、インタラクションのイベント コールバックが、本来よりも遅れて実行されます。タイマーがファーストパーティ コードで発生している場合は、タイマーを制御できます。必要かどうかを評価するか、できるだけ作業を減らすようにしてください。ただし、サードパーティ スクリプトのタイマーは別の話です。多くの場合、サードパーティ スクリプトの動作を制御することはできません。サードパーティ コードのパフォーマンスの問題を修正するには、多くの場合、関係者と協力して、特定のサードパーティ スクリプトが必要かどうかを判断し、必要な場合は、サードパーティ スクリプト ベンダーに連絡して、ウェブサイトで発生する可能性のあるパフォーマンスの問題を修正するために何ができるかを判断する必要があります。
長いタスクを回避する
入力の遅延を軽減する方法の一つに、長いタスクを避けることがあります。メインスレッドの作業が過剰で、インタラクション中にメインスレッドがブロックされると、長いタスクが完了する前に、入力遅延が発生します。
タスクで実行する作業量を最小限に抑える(メインスレッドで実行する作業量を可能な限り少なくするよう常に努める必要があります)だけでなく、長いタスクを分割することで、ユーザー入力に対する応答性を高めることができます。
インタラクションの重複に注意する
INP の最適化で特に難しいのは、インタラクションが重複している場合です。インタラクションの重複とは、ある要素を操作した後、最初のインタラクションで次のフレームがレンダリングされる前に、ページを再度操作することです。
やり取りの重複の原因は、ユーザーが短時間に多くのやり取りを行ったという単純なものである可能性があります。これは、ユーザーがフォーム フィールドに入力するときに発生することがあります。この場合、非常に短い時間内に多くのキーボード操作が行われる可能性があります。キーイベントの処理が特に高負荷な場合(バックエンドにネットワーク リクエストを行うオートコンプリート フィールドの一般的なケースなど)、次の 2 つのオプションがあります。
- 入力のデバウンスを検討して、特定の期間にイベント コールバックが実行される回数を制限します。
AbortControllerを使用して送信fetchリクエストをキャンセルし、メインスレッドがfetchコールバックの処理で混雑しないようにします。注:AbortControllerインスタンスのsignalプロパティを使用して、イベントを中止することもできます。
インタラクションの重複による入力遅延の増加のもう 1 つの原因は、コストの高いアニメーションです。特に、JavaScript のアニメーションでは requestAnimationFrame 呼び出しが多数発生し、ユーザー操作の妨げになる可能性があります。これを回避するには、可能な限り CSS アニメーションを使用して、コストのかかるアニメーション フレームのキューイングを避けます。ただし、この場合は、アニメーションが主に GPU とコンポジタ スレッドで実行され、メインスレッドで実行されないように、合成されていないアニメーションを避けるようにしてください。
まとめ
入力遅延はインタラクションの実行にかかる時間の大部分を占めていないかもしれませんが、インタラクションの各部分には短縮できる時間が含まれていることを理解しておくことが重要です。入力遅延が長い場合は、短縮できる可能性があります。タイマー コールバックの繰り返しを避け、長いタスクを分割し、インタラクションの重複の可能性を認識することで、入力遅延を減らし、ウェブサイトのユーザーのインタラクティビティを向上させることができます。
Unsplash の Erik Mclean によるヒーロー画像。