INPの改善:Reactアプリの「もっさり感」を解消する方法

ダッシュボードの動作が重く感じられる。APIは高速。Lighthouseのスコアは良好。それなのに、クリックするたびにラグが発生する。

それはINPの問題です。

Interaction to Next Paint (INP) は、ページがユーザーの操作に反応するまでにかかる時間を測定します。2024年3月に First Input Delay (FID) に代わって導入されました。FIDは最初のクリックのみを対象としていましたが、INPはすべてのインタラクションを監視します。

INPスコアが200ms未満であれば高速に感じられ、500msを超えると動作が重く感じられます。

INPを改善するには、以下の3つのフェーズに分けて考えます。

  • Input Delay(入力遅延) – クリックしてからコードが実行されるまでの時間。メインスレッドがビジー状態のときに発生します。
  • Processing Time(処理時間) – 関数やReactのステート更新が実行されている時間。
  • Presentation Delay(描画遅延) – コードの実行が完了してから、ブラウザが画面をペイント(描画)するまでの時間。

Input Delayの改善

長いタスクはメインスレッドをブロックします。タスクの実行時間が50msを超えると、クリック操作が停滞します。scheduler.yield() を呼び出して長いタスクを小さなチャンクに分割することで、ブラウザがタスクの合間にクリックを処理できるようにします。

Processing Timeの改善

ReactのTransition APIを使用して、UIの応答性を維持します。

  • startTransition – 緊急性の低い更新をラップします。Reactは重い更新を一時停止して、新しいクリックを処理できます。
  • useDeferredValue – 即座に更新する必要のない値を遅延させます。

これらのAPIはコード自体の速度を上げるものではありません。コードを「中断可能(interruptible)」にすることで、INPを低下させます。

Presentation Delayの改善

DOM要素が多すぎると、ペイントが遅くなります。

  • CSSで content-visibility: auto を適用し、画面外の要素のレンダリングをスキップします。
  • レイアウト・スラッシング(Layout Thrashing)を防ぎます。同じループ内でスタイルの読み取りと書き込みを繰り返さないでください。代わりに、読み取りと書き込みをまとめて(バッチ処理して)行います。
  • 長いリストは仮想化(Virtualize)します。

測定方法

Lighthouseはラボ環境で実行されるため、実際のユーザーのようにボタンをクリックすることはできません。web-vitals ライブラリをインストールして、実際のユーザーからのデータを取得しましょう。

出典: https://dev.to/ahmed_mahmoud360/fixing-inp-field-notes-on-interaction-to-next-paint-in-a-react-app-32fa