react-native-best-practices について
React Native アプリの性能を調査・改善する開発者向けガイドです。JavaScript、ネイティブコード、バンドルを対象に、測定に基づく対策を優先度順に整理しています。
主な機能
- 01FPS と再レンダリングの分析
- 02バンドルとアプリサイズの分析
- 03起動時間と TTI の改善指針
- 04JavaScript とネイティブのメモリ確認
- 05ネイティブ性能とモジュールの指針
活用シーン
- 01UI のカクつきやアニメーションのフレーム落ちの調査
- 02アプリの起動時間短縮やバンドル縮小
- 03JavaScript またはネイティブのメモリリーク追跡
- 04測定結果に基づく性能変更のレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ callstackincubator/ agent-skills --skill react-native-best-practicesインストール後、Claude Code で/react-native-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
POWER.mdagents/openai.yamlreferences/bundle-analyze-app.mdbundle-analyze-js.mdbundle-barrel-exports.mdbundle-code-splitting.mdbundle-hermes-mmap.mdbundle-library-size.mdbundle-native-assets.mdbundle-r8-android.mdbundle-tree-shaking.mdjs-animations-reanimated.mdjs-atomic-state.mdjs-bottomsheet.mdjs-concurrent-react.mdjs-lists-flatlist-flashlist.mdjs-measure-fps.mdjs-memory-leaks.mdjs-profile-react.mdjs-react-compiler.mdjs-uncontrolled-components.mdnative-android-16kb-alignment.mdnative-measure-tti.mdnative-memory-leaks.mdnative-memory-patterns.mdnative-platform-setup.mdnative-profiling.mdnative-sdks-over-polyfills.mdnative-threading-model.mdnative-turbo-modules.md詳細
React Native のベストプラクティス
概要
JavaScript/React、ネイティブ(iOS/Android)、バンドルの最適化を扱う、React Native アプリケーションのパフォーマンス最適化ガイドです。Callstack の「Ultimate Guide to React Native Optimization」に基づいています。
適用するタイミング
次のような場合に、これらのガイドラインを参照してください。
- 動作が遅い、またはカクつく UI やアニメーションのデバッグ
- メモリリーク(JS またはネイティブ)の調査
- アプリの起動時間(TTI)の最適化
- バンドルまたはアプリのサイズの削減
- ネイティブモジュール(Turbo Modules)の作成
- React Native のパフォーマンスのプロファイリング
- パフォーマンスを目的とした React Native コードのレビュー
セキュリティに関する注意事項
- これらのリファレンスに記載されているシェルコマンドは、ローカルでの開発作業として扱ってください。実行前に内容を確認し、バージョンを固定したツールを優先するとともに、リモートスクリプトをシェルに直接パイプで渡すことは避けてください。
- サードパーティのライブラリやプラグインは、通常のサプライチェーン管理が引き続き必要な依存関係として扱ってください。バージョンを固定し、出所を確認したうえで、標準のレビュー手順に従って更新してください。
- リモートチャンクの読み込みは、ファーストパーティのアーティファクト配信に限ってください。アプリに同梱するチャンク、または署名済みの CI リリースマニフェストを優先してください。ホストされたチャンクは、管理下にある信頼できる HTTPS オリジンから取得し、現在のアプリリリースに固定する必要があります。
優先度順のガイドライン
| 優先度 | カテゴリ | 影響度 | プレフィックス |
|---|---|---|---|
| 1 | FPS と再レンダー | 重大 | js-* |
| 2 | バンドルサイズ | 重大 | bundle-* |
| 3 | TTI の最適化 | 高 | native-*, bundle-* |
| 4 | ネイティブパフォーマンス | 高 | native-* |
| 5 | メモリ管理 | 中~高 | js-*, native-* |
| 6 | アニメーション | 中 | js-* |
影響度のラベルはトリアージの目安です。まず重大、次に高、証拠が示す場合は中の順に対応してください。
クイックリファレンス
最適化ワークフロー
パフォーマンスの問題には、次のサイクルに従ってください。測定 → 最適化 → 再測定 → 検証
- 測定:変更前にベースラインのメトリクスを記録します。実行時の問題では、利用可能な場合、コミットタイムライン、再レンダー回数、遅いコンポーネント、最も負荷の高いコミットの内訳、起動時間/TTI を優先してください。コンポーネントツリーの深さや数は補足情報として任意であり、これらの代わりにはなりません。測定によってレンダーまたは FPS の問題が確認されていない場合は、メモ化、アトミックな状態管理、コンパイラーの変更を推奨しないでください。
- 最適化:該当するリファレンスにある、対象を絞った修正を適用します。
- 再測定:同じ測定を行い、更新後のメトリクスを取得します。
- 検証:改善を確認します(例:FPS が 45→60、TTI が 3.2s→1.8s、バンドルが 2.1MB→1.6MB)。
メトリクスが改善しなかった場合は、変更を元に戻して、次に推奨される修正を試してください。
レビュー時のガードレール
- API 固有の修正を提案する前に、ライブラリのバージョンを確認してください。例:FlashList v2 では
estimatedItemSizeは非推奨のため、存在しないことを指摘しないでください。 - 動作に明らかな誤りがある場合、またはプロファイリングでその値に関連する無駄な処理が確認された場合を除き、
useMemoやuseCallbackの依存関係の変更を提案しないでください。 - 古いクロージャーを憶測で報告しないでください。問題として指摘する前に、古い値の読み取り経路、再現手順、またはプロファイラーの証拠を示してください。
- フローをプロファイリングする際は、対象のインタラクション自体を測定してください。コンポーネントツリーの深さやコンポーネント数を、主なパフォーマンスの根拠として扱わないでください。
重要:FPS と再レンダリング
まずプロファイルを取得します:
agent-device react-devtools status
agent-device react-devtools wait --connected
agent-device react-devtools profile start
agent-device react-devtools profile stop
agent-device react-devtools profile slow --limit 5
agent-device react-devtools profile rerenders --limit 5
agent-device react-devtools profile timeline --limit 20
profile start と profile stop の間に、通常の agent-device コマンドを使って対象の操作を実行します。
agent-device が使用できない場合の手動での代替手段:Metro(j)または Dev Menu から React Native DevTools を開き、Profiler タブを使って、同じ操作を記録します。
リリースビルドで React コンポーネントをプロファイリングするには、まず @callstack/inspector を接続して、React DevTools がリリースアプリにアタッチできるようにしてから、上記の agent-device react-devtools の手順を実行します。
一般的な修正方法:
- 長いリストでは、ScrollView を FlatList/FlashList/Legend List に置き換えます
- プロファイリングで連鎖的な再レンダリングが確認された場合は、React Compiler を使って自動メモ化します
- プロファイリングでストア/コンテキストの広範な更新が確認された場合は、アトミックな状態管理(Jotai/Zustand)を使って再レンダリングを減らします
- コストの高い計算には
useDeferredValueを使います
重要:バンドルサイズ
バンドルを分析します:
npx react-native bundle \
--entry-file index.js \
--bundle-output output.js \
--platform ios \
--sourcemap-output output.js.map \
--dev false --minify true
npx source-map-explorer output.js --no-border-checks
最適化後の改善を確認します:
# Record baseline size before changes
ls -lh output.js # e.g., Before: 2.1 MB
# After applying fixes, re-bundle and compare
npx react-native bundle --entry-file index.js --bundle-output output.js \
--platform ios --dev false --minify true
ls -lh output.js # e.g., After: 1.6 MB (24% reduction)
一般的な修正方法:
- バレルインポートを避けます(ソースから直接インポートします)
- Hermes API とメソッドの対応状況を確認してから、不要な Intl ポリフィルのみを削除します
- ツリーシェイキングを評価します(Expo SDK 52 以降の実験的な未使用インポート/エクスポートの削除、または、すでに設定済みの場合に限り Re.Pack を使用します)
- Android のネイティブコードの縮小には R8 を有効にします
高:TTI の最適化
TTI を測定します:
- マーカーには
react-native-performanceを使います - コールドスタートのみを測定します(ウォーム/ホット/事前ウォームアップは除外します)
一般的な修正方法:
- React Native 0.78 以前では、Hermes の mmap を有効にするため、Android の JS バンドル圧縮を無効にします
- ネイティブナビゲーション(react-native-screens)を使います
- よく使う、コストの高い画面を、遷移前にプリロードします
高:ネイティブパフォーマンス
ネイティブをプロファイルします:
- iOS:Xcode Instruments → Time Profiler
- Android:Android Studio → CPU Profiler
一般的な修正方法:
- 負荷の高いネイティブ処理にはバックグラウンドスレッドを使います
- Turbo Module のメソッドは同期より非同期を優先します
- クロスプラットフォームでパフォーマンスが重要なコードには C++ を使います
参考資料
コード例を含む詳細なドキュメントは references/ にあります:
JavaScript/React(js-*)
| ファイル | 影響度 | 説明 |
|---|---|---|
| js-lists-flatlist-flashlist.md | CRITICAL | ScrollView を仮想化リストに置き換えます |
| js-profile-react.md | MEDIUM | agent-device react-devtools によるプロファイリング |
| js-measure-fps.md | HIGH | FPS の監視と測定 |
| js-memory-leaks.md | MEDIUM | JS メモリリークの調査 |
| js-atomic-state.md | HIGH | Jotai/Zustand のパターン |
| js-concurrent-react.md | HIGH | useDeferredValue、useTransition |
| js-react-compiler.md | HIGH | 自動メモ化 |
| js-animations-reanimated.md | MEDIUM | Reanimated のワークレット |
| js-bottomsheet.md | HIGH | ボトムシートの最適化 |
| js-uncontrolled-components.md | HIGH | TextInput の最適化 |
ネイティブ(native-*)
| ファイル | 影響度 | 説明 |
|---|---|---|
| native-turbo-modules.md | HIGH | 高速なネイティブモジュールの構築 |
| native-sdks-over-polyfills.md | HIGH | ネイティブライブラリと JS ライブラリの比較 |
| native-measure-tti.md | HIGH | TTI 測定のセットアップ |
| native-threading-model.md | HIGH | Turbo Module のスレッド |
| native-profiling.md | MEDIUM | Xcode/Android Studio でのプロファイリング |
| native-platform-setup.md | MEDIUM | iOS/Android ツールガイド |
| native-view-flattening.md | MEDIUM | ビューヒエラルキーのデバッグ |
| native-memory-patterns.md | MEDIUM | C++/Swift/Kotlin のメモリ |
| native-memory-leaks.md | MEDIUM | ネイティブメモリリークの調査 |
| native-android-16kb-alignment.md | CRITICAL | Google Play 向けサードパーティライブラリのアライメント |
バンドル(bundle-*)
| ファイル | 影響度 | 説明 |
|---|---|---|
| bundle-barrel-exports.md | CRITICAL | バレルインポートを避ける |
| bundle-analyze-js.md | CRITICAL | JS バンドルの可視化 |
| bundle-tree-shaking.md | HIGH | デッドコードの除去 |
| bundle-analyze-app.md | HIGH | アプリサイズの分析 |
| bundle-r8-android.md | HIGH | Android コードの縮小 |
| bundle-hermes-mmap.md | HIGH | バンドル圧縮を無効化 |
| bundle-native-assets.md | HIGH | アセットカタログのセットアップ |
| bundle-library-size.md | MEDIUM | 依存関係の評価 |
| bundle-code-splitting.md | MEDIUM | リモートチャンク読み込みの保護策 |
問題 → スキルの対応表
| 問題 | まず試すもの |
|---|---|
| アプリの動作が遅い/ぎこちない | js-measure-fps.md → js-profile-react.md |
| 再レンダリングが多すぎる | js-profile-react.md → js-react-compiler.md |
| 起動が遅い(TTI) | native-measure-tti.md → bundle-analyze-js.md |
| アプリのサイズが大きい | bundle-analyze-app.md → bundle-r8-android.md |
| メモリ使用量が増え続ける | js-memory-leaks.md または native-memory-leaks.md |
| アニメーションでフレーム落ちが発生する | js-animations-reanimated.md |
| ボトムシートの動作がぎこちない/再レンダリングが発生する | js-bottomsheet.md → js-animations-reanimated.md |
| リストのスクロールがぎこちない | js-lists-flatlist-flashlist.md |
| TextInput の入力が遅れる | js-uncontrolled-components.md |
| ネイティブモジュールの動作が遅い | native-turbo-modules.md → native-threading-model.md |
| ネイティブライブラリのアラインメントに問題がある | native-android-16kb-alignment.md |
クレジット
Callstack による「The Ultimate Guide to React Native Optimization」に基づいています。