mcpField
E
expo-best-practices

expo-best-practices

github.com/ofershap開発1143 回インストール37 週間前に更新
リポジトリ

expo-best-practices について

Expo または React Native のコードを扱う AI エージェント向けのスキルです。ナビゲーション、ネイティブ設定、プラットフォーム別コード、ストレージ、アップデートなどの開発パターンをまとめています。

主な機能

  1. 01Expo Router によるファイルベースのナビゲーション
  2. 02設定プラグインによるネイティブ設定
  3. 03EAS Build によるネイティブビルド
  4. 04プラットフォーム別コードのパターン
  5. 05画像、フォント、機密データ向け Expo パッケージ
  6. 06型付きナビゲーションパラメーター

活用シーン

  1. 01ルートと共通レイアウトの構成
  2. 02ファイルを直接編集せずにネイティブ設定
  3. 03機密データとプッシュ通知の処理
  4. 04現行 API を使った Expo アプリの保守

インストール

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

$npx skills add https://github.com/ofershap/expo-best-practices --skill expo-best-practices

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

詳細

使用する場面

Expo または React Native のコードを扱う場合に、このスキルを使用します。現在のベストプラクティスを学び、古いパターン、手動でのネイティブ設定、非推奨 API によって AI エージェントがよく犯す間違いを防ぎます。

重要なルール

1. ナビゲーションには Expo Router を使用する

誤り(エージェントがよく行う方法):

import { createStackNavigator } from "@react-navigation/stack";
const Stack = createStackNavigator();
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

正しい方法:

app/
  _layout.tsx
  index.tsx
  settings.tsx

app/ ディレクトリの規約を使用します。ファイルは自動的にルートになります。新しい Expo プロジェクトには、デフォルトで Expo Router が含まれています。

理由: Expo Router は React Navigation を基盤とし、ファイルベースのルーティング、型付きルート、ディープリンクを提供し、Expo CLI と統合されています。React Navigation を手動で設定するのは冗長であり、Expo Router の機能を活用できません。

2. ナビゲーション構造には expo-router のレイアウトを使用する

誤り:

// Each screen manually defines its own layout

正しい方法:

// app/_layout.tsx
import { Stack } from "expo-router";
export default function RootLayout() {
  return <Stack />;
}

理由: _layout.tsx は、共通のナビゲーション構造、タブ、スタック、ネストされたレイアウトを定義します。ナビゲーション設定を一元化できます。

3. ネイティブビルドには EAS Build を使用する

誤り:

expo build:ios
expo build:android

正しい方法:

eas build --platform ios
eas build --platform android

理由: expo build は非推奨です。EAS Build は、より優れたキャッシュ、認証情報の管理、ネイティブモジュールのサポートを備えた、現在のクラウドビルドサービスです。

4. ネイティブ設定には Expo config plugins を使用する

誤り:

# Manually editing
ios/MyApp/Info.plist
android/app/src/main/AndroidManifest.xml

正しい方法:

// app.config.ts
import { ConfigPlugin } from "expo/config-plugins";
const withMyApiKey: ConfigPlugin<{ apiKey: string }> = (config, { apiKey }) => {
  config = withInfoPlist(config, (c) => {
    c.modResults["MY_API_KEY"] = apiKey;
    return c;
  });
  return config;
};
export default {
  plugins: [["withMyApiKey", { apiKey: process.env.API_KEY }]],
};

理由: ネイティブファイルを直接編集すると、prebuild 時に上書きされます。Config plugins はビルド時にネイティブファイルを変更するため、prebuild 後も変更が保持されます。

5. プラットフォーム固有のコードには、プラットフォーム拡張子または Platform.select を使用する

誤り:

if (Platform.OS === "ios") {
  return <IOSComponent />;
}
return <AndroidComponent />;

正しい方法:

MyComponent.ios.tsx
MyComponent.android.tsx

または:

import { Platform } from "react-native";
const styles = StyleSheet.create({
  container: Platform.select({
    ios: { paddingTop: 20 },
    android: { paddingTop: 0 },
  }),
});

理由: プラットフォーム固有のファイル拡張子を使うと、バンドラーは各プラットフォームに適したコードのみを含めます。Platform.select を使うと、適切な場合に条件分岐を 1 つのファイルにまとめられます。

6. React Native Image の代わりに expo-image を使用する

誤り:

import { Image } from "react-native";
<Image source={{ uri: url }} style={styles.image} />;

正しい方法:

import { Image } from "expo-image";
<Image source={url} contentFit="cover" style={styles.image} />;

理由: expo-image はキャッシュ、プレースホルダー、blurhash、より優れたパフォーマンスを提供します。React Native の Image には、これらの機能がありません。

7. カスタムフォントには expo-font を使用する

誤り:

# Manual font linking via native projects

正しい方法:

import * as Font from "expo-font";
await Font.loadAsync({
  CustomFont: require("./assets/fonts/CustomFont.ttf"),
});

理由: expo-font はフォントの読み込みを処理し、ネイティブ設定を手動で行う必要をなくします。

8. 機密データには expo-secure-store を使用する

誤り:

import AsyncStorage from "@react-native-async-storage/async-storage";
await AsyncStorage.setItem("authToken", token);

正しい方法:

import * as SecureStore from "expo-secure-store";
await SecureStore.setItemAsync("authToken", token);

理由: AsyncStorage は暗号化されていません。expo-secure-store は、トークンやシークレットの保存にプラットフォームのキーチェーン/Keystore を使用します。

9. プッシュ通知には expo-notifications を使用する

誤り:

// Manual Firebase/APNs setup, native configuration

正しい方法:

import * as Notifications from "expo-notifications";
const token = await Notifications.getExpoPushTokenAsync();

理由: expo-notifications は、iOS と Android のプッシュ通知設定を抽象化します。Firebase/APNs を手動で設定する方法は、エラーが発生しやすく、プラットフォームごとの対応が必要です。

10. 設定には app.json または app.config.ts を使用する

誤り:

# Editing Info.plist or AndroidManifest.xml directly

正しい方法:

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "plugins": ["expo-router"]
  }
}

理由: Expo は app.json/app.config.ts からネイティブ設定を管理します。直接編集すると、prebuild 時に上書きされます。

11. OTA アップデートには expo-updates を使用する

誤り:

import codePush from "react-native-code-push";
export default codePush(MyApp);

正しい方法:

import * as Updates from "expo-updates";
await Updates.checkForUpdateAsync();

理由: expo-updates は EAS および Expo のアップデートサービスと統合されています。CodePush には別途設定が必要で、Expo プロジェクトでは重複する機能です。

12. 型付きナビゲーションパラメーターには TypeScript を使用する

誤り:

router.push("/profile");

正しい方法:

import { router } from "expo-router";
router.push({ pathname: "/profile/[id]", params: { id: userId } });

ルートファイルでルートパラメーターを定義します。TypeScript と併用すると、Expo Router は型付きルートヘルパーを提供します。

理由: 型付きパラメーターは実行時エラーを防ぎ、エディターのサポートを向上させます。

パターン

  • URL に対応するファイル名を付けて、app/ の下にルートを作成します
  • 共通のレイアウト、タブ、スタックには _layout.tsx を使用します
  • プラットフォーム固有のコンポーネントは Component.ios.tsx と Component.android.tsx に配置します
  • ネイティブ設定を変更する場合は、app.json/app.config.ts で expo config plugins を使用します
  • EAS Build のプロファイルには eas.json を使用します

アンチパターン

  • Expo プロジェクトで React Navigation を手動で設定しないでください
  • expo build を使用しないでください(EAS Build を使用してください)
  • マネージドワークフローで ios/ や android/ を直接編集しないでください
  • 認証トークンやシークレットに AsyncStorage を使用しないでください
  • expo-image が利用できる場合は、React Native の Image を使用しないでください
  • Expo プロジェクトで CodePush を使用しないでください(expo-updates を使用してください)

コメント