入力ハンドラをデバウンスする

入力ハンドラは、フレームの完了を妨げ、追加の不要なレイアウト作業を引き起こす可能性があるため、アプリのパフォーマンス上の問題の原因となる可能性があります。

入力ハンドラは、次のようにアプリのパフォーマンスの問題の原因となる可能性があります。 フレームの完了を妨げることがあり、追加で不要な結果を引き起こす 説明します。

概要

  • 長時間実行される入力ハンドラを避ける。スクロールをブロックできます
  • 入力ハンドラではスタイルを変更しないでください。
  • ハンドラをデバウンスする。イベント値を保存し、次の requestAnimationFrame コールバックでスタイルの変更を処理します。

長時間実行される入力ハンドラを避ける

最速のケースでは、ユーザーがページを操作すると、ページのコンポジタ スレッドがユーザーのタップ入力を受け取り、単にコンテンツを移動します。この場合、JavaScript、レイアウト、スタイル、ペイントを行うメインスレッドによる処理は不要です。

軽量スクロールコンポジタのみです。

ただし、touchstarttouchmovetouchend などの入力ハンドラをアタッチした場合、コンポジタ スレッドは、preventDefault() を呼び出してタッチ スクロールの実行を停止することを選択できるため、このハンドラの実行が完了するまで待つ必要があります。preventDefault() を呼び出さなくても、コンポジタは待機する必要があり、ユーザーのスクロールがブロックされ、スタッタリングやフレーム欠落が発生する可能性があります。

高スクロールJavaScript でコンポジタがブロックされています。

要するに、実行する入力ハンドラが迅速に実行され、コンポジタがジョブを実行できるようにする必要があります。

入力ハンドラでスタイルを変更しない

入力ハンドラ(スクロールやタップなど)は、requestAnimationFrame コールバックの直前に実行されるようにスケジュール設定されます。

これらのハンドラのいずれかで視覚的な変更を加えると、requestAnimationFrame の開始時に、スタイルの変更が保留状態になります。その後、requestAnimationFrame コールバックの開始時にビジュアル プロパティを読み取ると、大規模で複雑なレイアウトとレイアウト スラッシングを回避するのアドバイスが示すように、強制同期レイアウトがトリガーされます。

高スクロールJavaScript でコンポジタがブロックされています。

スクロール ハンドラのデバウンス

上記の両方の問題の解決方法は同じです。常に視覚的な変化を次の requestAnimationFrame コールバックにデバウンスする必要があります。

function onScroll (evt) {

    // Store the scroll value for laterz.
    lastScrollY = window.scrollY;

    // Prevent multiple rAF callbacks.
    if (scheduledAnimationFrame)
    return;

    scheduledAnimationFrame = true;
    requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll', onScroll);

これにより、入力ハンドラを軽量化できるという利点もあります。計算コストの高いコードのスクロールやタップなどの処理がブロックされなくなるという利点もあります。