Reactベストプラクティス
ReactとNext.jsの性能問題を、影響の大きい領域から確認する。 小さなmicro optimizationより、network waterfall、bundle、server/client境界を先に扱う。
1. 非同期waterfallを解消する
- 独立したI/Oは同時に開始し、まとめて待つ。
- 条件分岐で不要な
awaitは、その分岐の中へ移す。 - API routeではpromiseを早く開始し、必要になる地点まで
awaitを遅らせる。 - component treeが直列fetchを生む場合は、data dependencyに合わせて構造を変える。
- streamingできる境界にはSuspenseを置き、page全体を遅い処理へ巻き込まない。
2. bundleを減らす
- barrel exportが大きなmodule graphを引き込む場合はdirect importへ変える。
- 重いcomponentは必要な画面または操作でdynamic importする。
- analyticsなど非主要なthird-party codeはhydration後へ遅延する。
- featureが無効な場合、そのmoduleをloadしない構造にする。
- hoverまたはfocusで次に必要なresourceを予測できる場合だけpreloadする。
- bundle analyzerまたはbuild outputで改善を確認する。
3. server境界を整える
- Server Actionも外部入力を受けるAPIとして認証・認可する。
- request内の重複fetchはrequest scopeでdeduplicateする。
- requestをまたぐcacheには期限、size、invalidationを持たせる。
- Server ComponentからClient Componentへ渡すdataを必要最小限にする。
- 同じdataを異なる形で重複serializationしない。
- module scopeへrequest固有のmutable stateを置かない。
- responseを待つ必要がない処理は、frameworkが提供する完了後処理へ分離する。
4. client dataとeventを管理する
- 同一resourceへのclient requestをdeduplicateする仕組みを使う。
- global event listenerをcomponentごとに重複登録しない。
- scrollやtouchのlistenerは、preventDefaultが不要ならpassiveにする。
- local storageのschemaへversionを持たせ、保存量を小さくする。
5. 再描画を減らす
- render中に導出できる値をeffectとstateで二重管理しない。
- interaction起因の処理はeffectではなくevent handlerへ置く。
- 高頻度だが描画に不要な値はrefで保持する。
- 高コストな初期値は
useStateのlazy initializerへ渡す。 - state更新が前値に依存する場合はfunctional updateを使う。
- 入力応答を優先すべき更新はtransitionまたはdeferred valueを検討する。
- simpleな式に
useMemoを付けず、計測できる高コスト処理へ限定する。 - componentを別componentのrender中に定義しない。
6. renderingを整える
- 長いoff-screen contentには
content-visibilityを検討する。 - static JSXをcomponent外へ出す。
- conditional renderingで
0などが意図せず表示されない形にする。 - SVG自体よりwrapperのtransformをanimationする。
- hydration mismatchを警告抑制だけで隠さず、serverとclientの値が違う理由を直す。
- scriptは依存関係に応じて
deferまたはasyncを使う。
7. JavaScript最適化を最後に行う
繰り返しlookupにはMapまたはSet、複数passには一つのloop、不要な処理にはearly returnを検討する。 ただし、実測で問題になっていない読みやすい処理を、複雑な低水準実装へ置き換えない。
検証する
- network requestの開始時刻と依存関係
- routeまたはchunkごとのbundle size
- server responseとstreaming開始時間
- React profilerでのrender回数とduration
- Core Web Vitalsまたは対象interactionのlatency
変更前後を同じ条件で比較する。 推測だけで性能改善を主張しない。
出典
- [vercel-labs/agent-skills: react-best-practices](https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices)
- MIT License
- 本文は公式skillの優先順位を日本語の監査・修正手順へ再構成した派生文書である。