react-performance-optimization について
React 開発者向けに、描画、状態、バンドル、リストの最適化を案内するスキルです。Profiler でボトルネックを特定し、効果を測定してから最適化する方針が特徴です。
主な機能
- 01描画のボトルネック特定
- 02コンポーネントと計算結果のメモ化
- 03コード分割とオンデマンド読み込み
- 04大規模リストの仮想化
- 05状態管理と並行機能の指針
活用シーン
- 01不要なコンポーネント再描画の調査
- 02初回読み込みコード量の削減
- 03大規模リストやテーブルの応答性改善
- 04Profiler による最適化前後の比較
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ nickcrew/ claude-cortex --skill react-performance-optimizationインストール後、Claude Code で/react-performance-optimizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/code-splitting.mdcommon-pitfalls.mdconcurrent-features.mdmemoization.mdprofiling-debugging.mdstate-management.mdvirtualization.mdvalidation/rubric.yaml詳細
React パフォーマンスの最適化
メモ化、コード分割、仮想化、効率的なレンダリング戦略を通じて、React アプリケーションのパフォーマンスを最適化するための専門的なガイダンスです。
このスキルを使用するタイミング
- レンダリングが遅い React コンポーネントを最適化するとき
- 初回読み込みを高速化するためにバンドルサイズを削減するとき
- 大規模なリストやデータテーブルの応答性を向上させるとき
- 複雑なコンポーネントツリーで不要な再レンダリングを防ぐとき
- レンダリングの連鎖を減らすために状態管理を最適化するとき
- コード分割によって体感パフォーマンスを向上させるとき
- React DevTools Profiler でパフォーマンスの問題をデバッグするとき
コアコンセプト
React のレンダリング最適化
React は、props または state が変更されるとコンポーネントを再レンダリングします。不要な再レンダリングは CPU サイクルを無駄にし、ユーザー体験を損ないます。主な最適化手法:
- メモ化:コンポーネントのレンダリングと計算値をキャッシュします
- コード分割:初回読み込みを高速化するため、コードを必要に応じて読み込みます
- 仮想化:表示中のリスト項目のみをレンダリングします
- 状態の最適化:レンダリングの連鎖を最小限に抑えるよう状態を構成します
最適化のタイミング
- まずプロファイルする:React DevTools Profiler を使って実際のボトルネックを特定します
- 効果を測定する:最適化によってパフォーマンスが向上することを確認します
- 早すぎる最適化を避ける:高速なコンポーネントは最適化しないでください
クイックリファレンス
必要に応じて詳細なパターンや例を参照してください:
| トピック | 参照ファイル |
|---|---|
| React.memo、useMemo、useCallback のパターン | skills/react-performance-optimization/references/memoization.md |
| lazy/Suspense によるコード分割、バンドルの最適化 | skills/react-performance-optimization/references/code-splitting.md |
| 大規模なリストの仮想化(react-window) | skills/react-performance-optimization/references/virtualization.md |
| 状態管理の戦略、コンテキストの分割 | skills/react-performance-optimization/references/state-management.md |
| useTransition、useDeferredValue(React 18+) | skills/react-performance-optimization/references/concurrent-features.md |
| React DevTools Profiler、パフォーマンスの監視 | skills/react-performance-optimization/references/profiling-debugging.md |
| よくある落とし穴とアンチパターン | skills/react-performance-optimization/references/common-pitfalls.md |
最適化のワークフロー
1. ボトルネックを特定する
# Open React DevTools Profiler
# Record interaction → Analyze flame graph → Find slow components
次の点に注目してください:
- 黄色または赤色のバーが表示されるコンポーネント(レンダリングが遅い)
- 不要なレンダリング(props/state が同じ)
- レンダリングのたびに実行される負荷の高い計算
2. 対象を絞って最適化する
不要な再レンダリングの場合:
React.memoでコンポーネントをラップします- 安定した関数参照には
useCallbackを使用します - props 内のインラインオブジェクトや配列を確認します
負荷の高い計算の場合:
useMemoで結果をキャッシュします- 可能であれば計算をレンダリングの外に移します
大規模なリストの場合:
- react-window で仮想化を実装します
- 一意で適切なキーを使用します(インデックスは使わないでください)
初回読み込みが遅い場合:
React.lazyでコード分割を追加します- webpack-bundle-analyzer でバンドルサイズを分析します
- サイズの大きい依存関係には動的インポートを使用します
3. 改善を確認する
# Record new Profiler session
# Compare before/after metrics
# Ensure optimization actually helped
よくあるパターン
負荷の高いコンポーネントをメモ化する
import { memo } from 'react';
const ExpensiveList = memo(({ items, onItemClick }) => {
return items.map(item => (
<Item key={item.id} data={item} onClick={onItemClick} />
));
});
計算値をキャッシュする
import { useMemo } from 'react';
function DataTable({ items, filters }) {
const filteredItems = useMemo(() => {
return items.filter(item => filters.includes(item.category));
}, [items, filters]);
return <Table data={filteredItems} />;
}
安定した関数参照
import { useCallback } from 'react';
function Parent() {
const handleClick = useCallback((id) => {
console.log('Clicked:', id);
}, []);
return <MemoizedChild onClick={handleClick} />;
}
ルートをコード分割する
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
const Reports = lazy(() => import('./Reports'));
function App() {
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/reports" element={<Reports />} />
</Routes>
</Suspense>
);
}
大規模なリストを仮想化する
import { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={80}
width="100%"
>
{({ index, style }) => (
<div style={style}>{items[index].name}</div>
)}
</FixedSizeList>
);
}
よくある間違い
- 過剰なメモ化:単純で高速なコンポーネントはメモ化しないでください(オーバーヘッドが発生します)
- インラインオブジェクトや配列:新しい参照はメモ化を無効にします(
config={{ theme: 'dark' }}) - 依存関係の不足:useCallback/useMemo 内で古いクロージャが使われます
- キーにインデックスを使用する:リストの順序が変わると再調整が正しく行われません
- 単一の大きなコンテキスト:更新のたびに広範囲の再レンダリングが発生します
- プロファイリングをしない:測定せずに最適化すると時間を無駄にします
パフォーマンスのチェックリスト
最適化する前に:
- React DevTools でプロファイリングし、ボトルネックを特定します
- パフォーマンス指標のベースラインを測定します
最適化の目標:
- 安定した props を持つコストの高いコンポーネントをメモ化します
- useMemo で計算値をキャッシュします(実際にコストが高い場合)
- メモ化した子コンポーネントに渡す関数には useCallback を使用します
- ルートや大きなコンポーネントにコード分割を実装します
- 100 項目を超えるリストを仮想化します
- リスト項目には安定したキー(一意の ID。インデックスは不可)を指定します
- 更新頻度に応じて状態を分割します
- 応答性を高めるため、並行機能(useTransition、useDeferredValue)を使用します
最適化した後:
- 再度プロファイリングして改善を確認します
- バンドルサイズの削減を確認します(該当する場合)
- 機能にリグレッションがないことを確認します
リソース
- React Docs - Performance:https://react.dev/learn/render-and-commit
- React DevTools:プロファイリング用のブラウザー拡張機能
- react-window:https://github.com/bvaughn/react-window
- バンドルアナライザー:webpack-bundle-analyzer、rollup-plugin-visualizer
- Lighthouse:Chrome DevTools のパフォーマンス監査
コメント
Markdown 対応