プロファイラ API
この記事は古くなっており、今後更新されません。新しい React 日本語ドキュメントである ja.react.dev をご利用ください。
以下の新しいドキュメントで最新の React の使い方が学べます。
Profiler
を使って、React アプリケーションのレンダーの頻度やレンダーの「コスト」を計測することができます。
本機能の目的は、アプリケーション中の、低速でメモ化などの最適化が有効な可能性のある部位を特定する手助けをすることです。
補足:
プロファイリングには追加のオーバーヘッドが生じますので、本番ビルドでは無効化されます。
本番環境でプロファイリングを利用するために、React はプロファイリングを有効化した特別な本番用ビルドを提供しています。 このビルドの使用方法については fb.me/react-profiling をご覧ください。
使用法
Profiler
は React ツリー内の特定部位におけるレンダーのコストを計測するため、ツリー内のどこにでも追加できます。
2 つの props が必要です。id
(文字列)と、ツリー内のコンポーネントが更新を「コミット」した際に React が毎回呼び出す onRender
コールバック(関数)です。
例えば、Navigation
コンポーネントとその子孫のプロファイリングを行うには:
render(
<App>
<Profiler id="Navigation" onRender={callback}> <Navigation {...props} />
</Profiler>
<Main {...props} />
</App>
);
アプリケーション内の複数部位の計測を行うために複数の Profiler
コンポーネントを使うことができます:
render(
<App>
<Profiler id="Navigation" onRender={callback}> <Navigation {...props} />
</Profiler>
<Profiler id="Main" onRender={callback}> <Main {...props} />
</Profiler>
</App>
);
同一のサブツリー内の複数のコンポーネントで計測を行うために Profiler
コンポーネントをネストすることもできます:
render(
<App>
<Profiler id="Panel" onRender={callback}> <Panel {...props}>
<Profiler id="Content" onRender={callback}> <Content {...props} />
</Profiler>
<Profiler id="PreviewPane" onRender={callback}> <PreviewPane {...props} />
</Profiler>
</Panel>
</Profiler>
</App>
);
補足
Profiler
は軽いコンポーネントですが、必要な時にのみ利用すべきです。使うごとにアプリケーションに多少の CPU およびメモリオーバーヘッドが生じます。
onRender
コールバック
Profiler
には props として onRender
関数を渡す必要があります。
プロファイリングされているツリー内のコンポーネントが更新を「コミット」した際に、React がこの関数を毎回呼び出します。
この関数は、レンダー内容とかかった時間に関する情報を引数として受け取ります。
function onRenderCallback(
id, // the "id" prop of the Profiler tree that has just committed
phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
actualDuration, // time spent rendering the committed update
baseDuration, // estimated time to render the entire subtree without memoization
startTime, // when React began rendering this update
commitTime, // when React committed this update
interactions // the Set of interactions belonging to this update
) {
// Aggregate or log render timings...
}
それぞれを詳細に見てみましょう:
id: string
- コミットが起きたProfiler
のid
プロパティ。 複数のプロファイラを使用している場合にどのツリーにコミットが起きたのかを区別するのに使うことができます。phase: "mount" | "update"
- ツリーが初回マウントされたのか、props や state、フックの変更によって再レンダーされたのかを区別します。actualDuration: number
- 現在の更新でProfiler
とその子孫のレンダーに要した時間。 これが(React.memo
、useMemo
、shouldComponentUpdate
などの)メモ化をどれだけうまく有効に使えているかの指標となります。 理想的には、子孫要素は特定の props が変化した場合にのみ再レンダーされるため、初回マウント時以降にこの値は大幅に小さくなるはずです。baseDuration: number
-Profiler
ツリー内のそれぞれのコンポーネントの直近のrender
時間。 この値を使って最悪の場合のレンダーコスト(初回マウント時や、メモ化の一切ないツリーの場合)を見積もることができます。startTime: number
- 現在の更新のレンダーを React が開始した時刻に対応するタイムスタンプ。commitTime: number
- 現在の更新を React がコミットした時刻に対応するタイムスタンプ。 必要に応じてグループ化できるよう、1 コミット内のすべてのプロファイラ間でこの値は共有されます。interactions: Set
- 更新がスケジュールされた(render
やsetState
の呼び出しなどにより)際に trace された “interaction” の Set。
補足
更新の原因を特定するために interaction を利用可能ですが、trace 用の API は依然実験的です。
fb.me/react-interaction-tracing に詳細があります。