はじめに
本記事は、Profilerを触ってみたものを備忘録としてまとめたものになります。React Profilerコンポーネントを使って対象のコンポーネントのパフォーマンス情報を取得する処理を実装をしていきます。
Profiler
React の Profiler
は、コンポーネントのパフォーマンスを測定できる便利なツールです。
Profiler
を使用した簡単なコンポーネントを作ってみます。
import { Profiler } from 'react';
function SampleComponent() {
const onRenderCallback = (
id, // 測定対象のコンポーネントを識別するための一意の名前
phase, // "mount" か "update"
actualDuration // レンダリングにかかった時間
) => {
console.log(`${id}の${phase}にかかった時間: ${actualDuration}ms`);
};
return (
<Profiler id="SampleComponent" onRender={onRenderCallback}>
{/* 測定したいコンポーネントをここに */}
</Profiler>
);
}
上記の場合取得できる情報は次の通りです。
- id:対象のコンポーネントを一意に識別するID
- phase: "mount"(初回レンダリング)か"update"(再レンダリング)
- actualDuration: レンダリングにかかった時間(ミリ秒)
コンポーネントのパフォーマンスを計測してみる
意図的に重い処理を含むコンポーネントを作成し、Profilerでパフォーマンスを計測してみます。
import { Profiler, useState } from 'react';
// サンプルデータ用の配列
const sampleFoods = ['寿司', 'ラーメン', 'カレー', 'ピザ', '天ぷら'];
const sampleSports = ['サッカー', '野球', 'バスケ', 'テニス', '水泳'];
// サンプルデータ生成
const generateItems = (count) => Array.from({ length: count }, (_, i) => ({
id: Math.random().toString() + `_${i}`,
firstName: `名前${i}`,
lastName: `苗字${i}`,
favoriteFood: sampleFoods[i % sampleFoods.length],
favoriteSport: sampleSports[i % sampleSports.length],
email: `email${i}@example.com`
}));
// 重い処理のシミュレート用関数
const heavyProcess = (text) => {
let sum = 0;
for (let i = 0; i < 1000000; i++) {
sum += i;
}
const [displayText] = [`${text}`, sum];
return displayText;
};
function SampleList({ items }) {
const processedItems = items.map(item => ({
...item,
displayName: heavyProcess(`${item.firstName} ${item.lastName}`),
interests: heavyProcess(`好きな食べ物: ${item.favoriteFood}、好きなスポーツ: ${item.favoriteSport}`),
}));
// レンダリング時の処理時間を表示
const onRenderCallback = (id, phase, actualDuration) => {
console.log(`${id}の${phase}フェーズ: ${actualDuration.toFixed(1)}ms`);
};
return (
<Profiler id="SampleList" onRender={onRenderCallback}>
<div className="list">
{processedItems.map(item => (
<div key={item.id} className="item">
<h3>{item.displayName}</h3>
<p>{item.interests}</p>
<p>{item.email}</p>
</div>
))}
</div>
</Profiler>
);
}
export default function App() {
const [items] = useState(() => generateItems(200));
return <SampleList items={items} />;
}
上記のソースでサーバを立ち上げて、初回レンダリングと再レンダリングを実行してみます。
ブラウザの開発者ツールから確認したログは下記の通りです。
出力ログ
SampleListのmountフェーズ: 6.3ms
SampleListのupdateフェーズ: 2.9ms
Profilerを使うことで、mountフェーズ(初回レンダリング)とupdateフェーズ(再レンダリング)の処理時間が計測できました。