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