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

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

入力ハンドラは、アプリ内のパフォーマンスの問題の潜在的な原因となります。これらはフレームの完了を妨げ、追加の不要なレイアウト作業の原因になります。

  • 長時間実行される入力ハンドラを避けて、スクロールがブロックされないようにします。
  • 入力ハンドラではスタイルを変更しないでください。
  • ハンドラをデバウンスします。イベント値を格納し、次の 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);

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