mcpField
R
react-native-specialist

react-native-specialist

github.com/404kidwiz開発116 回インストール
リポジトリ

react-native-specialist について

React Native 開発者向けに、新アーキテクチャ、ネイティブモジュール、Expo のワークフローを扱うスキルです。アーキテクチャ選定、ネイティブ連携、パフォーマンス改善、トラブルシューティングを案内します。

主な機能

  1. 01新アーキテクチャのガイダンス
  2. 02TurboModules と Fabric の手順
  3. 03Expo と EAS の設定ガイダンス
  4. 04ネイティブクラッシュとブリッジの調査
  5. 05性能・アーキテクチャのチェックリスト

活用シーン

  1. 01旧 Bridge からのアプリ移行
  2. 02カスタムネイティブモジュールの作成
  3. 03Expo のビルド・更新ワークフロー設定
  4. 04描画やメモリーの問題調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/404kidwiz/claude-supercode-skills --skill react-native-specialist

インストール後、Claude Code で/react-native-specialistを入力して読み込まれたか確認します。

詳細

React Native スペシャリスト

目的

「New Architecture」(Fabric/TurboModules)、JSI、Expo のワークフローを専門とする、React Native 開発の専門知識を提供します。カスタムネイティブモジュールと最適化された JavaScript からネイティブへのブリッジを使用して、高性能なクロスプラットフォームのモバイルアプリケーションを構築します。

使用する場面

  • New Architecture を使用して高性能な React Native アプリを構築する
  • カスタムの Native Module や View Manager(TurboModules/Fabric)を作成する
  • Expo のパイプライン(EAS Build、Updates、Config Plugins)を設定する
  • ネイティブクラッシュ(Xcode/Android Studio)やブリッジのボトルネックをデバッグする
  • Old Architecture(Bridge)から New Architecture(JSI)に移行する
  • 複雑なネイティブ SDK(マップ、WebRTC、Bluetooth)を統合する

例

例 1:New Architecture への移行

シナリオ: Bridge から Fabric/TurboModules に、大規模な本番アプリを移行します。

実装:

  1. New Architecture のフラグを段階的に有効化しました
  2. Native Module を TurboModules に変換しました
  3. 複雑な UI 向けに Fabric コンポーネントを実装しました
  4. Codegen を使用してネイティブブリッジのコードを生成しました
  5. New Architecture を有効にして徹底的にテストしました

結果:

  • UI のレンダリングが 40% 高速化
  • バンドルサイズが 30% 縮小
  • ネイティブとの境界をまたぐ型安全性が向上
  • クラッシュレポートとデバッグが改善
例 2:カスタム Native Module

シナリオ: フィットネスアプリに Bluetooth Low Energy を統合する必要があります。

実装:

  1. TypeScript の Native Module インターフェースを作成しました
  2. ネイティブコード(iOS は Swift、Android は Kotlin)を実装しました
  3. クロスプラットフォームでアクセスできるように RNTurboModule を公開しました
  4. 適切なメモリ管理とライフサイクル処理を追加しました
  5. 包括的なエラー処理を実装しました

結果:

  • BLE の操作が両プラットフォームでシームレスに動作
  • 型安全なブリッジにより実行時エラーを防止
  • 従来のネイティブモジュールよりコード量を 50% 削減
  • RN のアップグレード後も保守可能
例 3:パフォーマンスの最適化

シナリオ: アプリでスクロールのカクつきやメモリの問題が発生しています。

実装:

  1. Hermes エンジンを有効化しました
  2. FlatList を FlashList に置き換えました
  3. メモ化(useMemo、useCallback)を実装しました
  4. 画像や負荷の高いコンポーネントに遅延読み込みを追加しました
  5. ネイティブブリッジの通信を最適化しました

結果:

  • スクロールが安定して 60fps で動作
  • メモリ使用量を 40% 削減
  • アプリの起動時間を 35% 短縮
  • クラッシュ率を 60% 削減

ベストプラクティス

アーキテクチャ
  • New Architecture:Fabric/TurboModules を有効にして使用します
  • Native Modules:型安全性のために Codegen を使用します
  • ナビゲーション:React Navigation または Expo Router を使用します
  • 状態管理:適切なソリューション(Zustand、Redux)を選択します
パフォーマンス
  • Hermes:起動と実行時のパフォーマンス向上のために有効にします
  • メモ化:useMemo、useCallback、React.memo を使用します
  • リスト:大規模なリストには FlashList を使用します
  • 画像:適切に遅延読み込みとキャッシュを行います
ネイティブ統合
  • ライフサイクル管理:アプリの状態変化を処理します
  • エラーバウンダリ:ネイティブエラーを適切に捕捉します
  • 権限:適切にリクエストし、処理します
  • テスト:定期的に両プラットフォームでテストします
開発
  • Expo ワークフロー:開発を迅速化するために Expo を使用します
  • EAS Build:CI/CD ビルドに使用します
  • Updates:OTA アップデートには EAS Update を使用します
  • TypeScript:すべてのコードに使用します


2. 意思決定フレームワーク

アーキテクチャの選択
Which architecture to use?
│
├─ **New Architecture (Default for 0.76+)**
│  ├─ **TurboModules:** Lazy-loaded native modules (Sync/Async).
│  ├─ **Fabric:** C++ Shadow Tree for UI (No bridge serialization).
│  ├─ **Codegen:** Type-safe spec for Native <-> JS communication.
│  └─ **Bridgeless Mode:** Removes the legacy bridge entirely.
│
└─ **Old Architecture (Legacy)**
   ├─ **Bridge:** Async JSON serialization (Slow for large data).
   └─ **Maintenance:** Only for unmigrated legacy libraries.
Expo と CLI の比較
機能Expo(Managed)React Native CLI(Bare)
セットアップ即時(create-expo-app)複雑(JDK、Xcode、Pods)
ネイティブコードConfig Plugins(ネイティブファイルを自動変更)ファイルを直接編集(AppDelegate.m)
アップグレードnpx expo install --fix(安定したセット)差分を手動で確認(Upgrade Helper)
ビルドEAS Build(クラウド)ローカルまたは CI(Fastlane)
アップデートEAS Update(OTA)CodePush(Microsoft)
パフォーマンス戦略
  1. JSI: C++ を直接呼び出します。JSON のシリアライズはありません。
  2. Reanimated: UI スレッドでアニメーションを実行します(Worklets)。
  3. FlashList: ビューを再利用します(FlatList を置き換えます)。
  4. Hermes: バイトコードを事前コンパイルします(起動が瞬時になります)。

危険な兆候 → mobile-developer(ネイティブ)にエスカレーション:

  • React Native エンジンのコア(C++)を変更する
  • 原因不明の ProGuard/R8 クラッシュをデバッグする
  • 低レベルの Metal/OpenGL レンダラーを一から作成する


3. コアワークフロー

ワークフロー 1:TurboModule の作成(新アーキテクチャ)

目標: JSI を介してネイティブのバッテリー残量に同期的にアクセスします。

手順:

  1. 仕様を定義する(NativeBattery.ts)

    import type { TurboModule } from 'react-native';
    import { TurboModuleRegistry } from 'react-native';
    
    export interface Spec extends TurboModule {
      getBatteryLevel(): number;
    }
    
    export default TurboModuleRegistry.getEnforcing<Spec>('RTNBattery');
    
  2. コードを生成する

    • yarn codegen を実行します。C++ インターフェースが生成されます。
  3. iOS を実装する(RTNBattery.mm)

    - (NSNumber *)getBatteryLevel {
      [UIDevice currentDevice].batteryMonitoringEnabled = YES;
      return @([UIDevice currentDevice].batteryLevel);
    }
    
    - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
        (const facebook::react::ObjCTurboModule::InitParams &)params {
      return std::make_shared<facebook::react::NativeBatterySpecJSI>(params);
    }
    
  4. Android を実装する(BatteryModule.kt)

    class BatteryModule(context: ReactApplicationContext) : NativeBatterySpec(context) {
      override fun getName() = "RTNBattery"
      
      override fun getBatteryLevel(): Double {
        val manager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
        return manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY).toDouble()
      }
    }
    


ワークフロー 3:Reanimated Worklets

目標: UI スレッドで 60fps のドラッグジェスチャーを実現します。

手順:

  1. セットアップ

    import { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
    import { GestureDetector, Gesture } from 'react-native-gesture-handler';
    
  2. 実装

    function Ball() {
      const offset = useSharedValue({ x: 0, y: 0 });
    
      const gesture = Gesture.Pan()
        .onUpdate((e) => {
          // UI スレッドで実行されます
          offset.value = { x: e.translationX, y: e.translationY };
        })
        .onEnd(() => {
          offset.value = withSpring({ x: 0, y: 0 }); // 元の位置に戻る
        });
    
      const style = useAnimatedStyle(() => ({
        transform: [{ translateX: offset.value.x }, { translateY: offset.value.y }]
      }));
    
      return (
        <GestureDetector gesture={gesture}>
          <Animated.View style={[styles.ball, style]} />
        </GestureDetector>
      );
    }
    


5. アンチパターンと注意点

❌ アンチパターン 1:「ブリッジをまたぐ」アニメーション

例:

  • useNativeDriver: false を指定して Animated.timing を使用する
  • useEffect でレイアウトを計算し、setState を呼び出す

問題点:

  • JS スレッドで実行されます。JS がデータを取得していてビジー状態の場合、フレームが落ちます。

推奨される方法:

  • Reanimated または useNativeDriver: true を使用します。
❌ アンチパターン 2:Hermes を使わない大きなバンドル

例:

  • Android で JSC(JavaScriptCore)を使用する
  • 起動に 5 秒かかる

問題点:

  • JSC は実行時に JS を解析します。Hermes は事前コンパイルされたバイトコードを実行します。

推奨される方法:

  • podfile / build.gradle で Hermes を有効にします(新しい Expo ではデフォルトです)。
❌ アンチパターン 3:レンダー中のスタイル定義

例:

  • style={{ width: 100, height: 100 }}

問題点:

  • レンダーのたびに新しいオブジェクトが作成され、差分計算が発生します。

推奨される方法:

  • コンポーネントの外で StyleSheet.create または const style = { ... } を使用します。


7. 品質チェックリスト

パフォーマンス:

  • Hermes: 有効化します。
  • メモ化: コストの高い props には useMemo/useCallback を使用します。
  • リスト: FlatList の代わりに FlashList を使用します。

アーキテクチャ:

  • 新アーキテクチャ: Fabric/TurboModules を有効化します(ライブラリが対応している場合)。
  • ナビゲーション: ネイティブ画面を使用します(React Navigation / Expo Router)。

ネイティブ:

  • 権限: 適切に処理します(拒否されてもクラッシュしないようにします)。
  • アップグレード: React Native のバージョンを新しい状態に保ちます(マイナーバージョンで 2 つ以内)。

アンチパターン

アーキテクチャのアンチパターン
  • ブリッジの過剰使用:旧アーキテクチャのブリッジを多用しています — 新アーキテクチャへ移行します
  • 不要なネイティブ実装:純粋な JS ロジックをネイティブでラップしています — シンプルに保ちます
  • 状態管理の乱立:複数の競合する状態管理ソリューションを使用しています — 1 つに統一します
  • ナビゲーションのネスト:ナビゲーターが深くネストしています — ナビゲーションを浅く保ちます
パフォーマンスのアンチパターン
  • すべてを再レンダリング:React.memo や最適化を使用していません — コンポーネントの再レンダリングを最適化します
  • FlatList の乱用:すべてのリストに FlatList を使用しています — 適切なリストコンポーネントを使用します
  • メモリーリーク:サブスクリプションをクリーンアップしていません — useEffect でクリーンアップします
  • ブリッジのボトルネック:ブリッジ通信が多すぎます — ブリッジをまたぐ呼び出しを最小限に抑えます
開発のアンチパターン
  • 本番環境でのデバッグモード:本番用にビルドしていません — 本番ビルドを必ずテストします
  • Hermes を使用しない:Hermes エンジンを使用していません — パフォーマンス向上のため有効化します
  • バンドルが大きい:バンドルを最適化していません — RAM バンドルと圧縮を使用します
  • 手動リンク:不要なのにネイティブのリンクを手動で行っています — 自動リンクを使用します
テストのアンチパターン
  • E2E テストがない:ユニットテストのみです — Maestro または Detox のテストを追加します
  • プラットフォーム条件分岐:プラットフォームのチェックが多すぎます — プラットフォーム間の違いを抽象化します
  • 寸法のハードコード:ピクセル値を固定しています — 相対サイズを使用します
  • testID がない:アクセシビリティ識別子がありません — テスト用に testID を追加します

コメント