OpenAIExpoOct 14, 2025, 1:15 PM

No rewrite required: How to bring Expo into mature native apps

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

openaienmodel: gpt-5-mini-2025-08-07

No rewrite required: How to bring Expo into mature native apps

Key Points

  • Adopt Expo incrementally—no full rewrite
  • Run React Native views inside existing native activities/controllers
  • Some libraries need extra lifecycle setup; expo-dev-client unsupported

Summary

Skip costly rewrites by adopting Expo incrementally in mature native apps. Expo is additive: you can ship a single screen or feature in React Native while keeping your existing native codebase. This makes it practical to gain faster iteration, platform parity, and shared components without discarding previous investments.

Key Points

  • Why adopt incrementally:

    • Ship a feature once to both iOS and Android for platform parity.
    • Create shared JS components (design systems, charting) to reduce duplication.
    • Allow product teams to build in JS while native engineers maintain platform infrastructure.
    • Migrate legacy screens gradually to reduce risk and maintenance costs.
  • High-level integration steps:

    • Create an Expo app inside your repo: npx create-expo-app my-project.
    • Organize project root so native code lives in ios/ and android/ (or configure a custom root).
    • Android: update Gradle files (settings.gradle, build.gradle, app/build.gradle, gradle.properties) for the React Native Gradle Plugin; add permissions to AndroidManifest.xml; initialize/load React Native in MainActivity; present a ReactActivity for RN views.
    • iOS: add React Native pods and run pod install; add a JS bundle build phase in Xcode; update Info.plist; create/present a ReactViewController to start the RN runtime.
    • Build your native app and start the Metro bundler from the RN directory: npx expo start.
  • Examples & resources:

  • Current limitations:

    • Some Expo libraries require additional lifecycle listener setup on Android/iOS.
    • expo-dev-client is not supported yet; more libraries will be added in future SDKs.

Practical advice

Start with a low-risk screen (onboarding, settings, chat view), keep responsibilities between native and JS clear, and use the example repositories as templates to validate integration before expanding Expo across the app.

Full Translation

Translations

A translation section that keeps the flow of the original article.

openaijamodel: gpt-5-mini-2025-08-07

成熟したネイティブアプリにExpoを導入する方法

概要

コストのかかる全面書き換えは不要です。ExpoとReact Nativeを使えば、アプリを段階的にモダン化でき、新しい画面や機能を数日で追加できます。成熟したネイティブアプリに新しい技術を導入するのは魅力的でありながらもハードルが高く感じられますが、Expoは付加的(additive)なので、アプリを全面的に書き換える必要はありません。1つの新機能(あるいは1つのビュー)ずつ導入し、既存アプリ内にきれいに統合できます。

以下では、なぜ段階的にExpoを採用する価値があるのかを示し、インクリメンタルにExpoを統合するための簡単な手順を紹介します。

インクリメンタル採用の一般的な理由

React NativeとExpoを段階的に採用する理由は多岐にわたりますが、本質的には「スピード」と「柔軟性」に集約されます。既存のネイティブ投資を損なったり、アプリを全面的に書き換えたりすることなく導入できる点が、多くのチームにとって魅力的です。

主なユースケース:

  • 妥協のないスピードと柔軟性

    • React Nativeが開発チームにもたらす高速なイテレーションと柔軟性を活かせます。
  • プラットフォームの整合性(platform parity)

    • iOSとAndroid両方で同時にリリースする必要がある新機能を、React Nativeで1回だけ実装して両プラットフォームに配布できます。例: 新しいメディアプレーヤーUIやサブスクリプションフロー。
  • 共有コンポーネント

    • 大規模組織では複数のアプリが重複する機能を持ちます。React Nativeで共有可能なJavaScriptコンポーネントを作れば重複を減らし一貫性を高められます。デザインシステムやカスタムチャートライブラリが典型的な出発点です。
  • ドメイン別に分かれたチーム運用

    • 全員がネイティブのエキスパートである必要はありません。モバイルプラットフォームのエンジニアは基盤となるiOS/Androidのインフラを維持し、プロダクトチームはReact Nativeで機能を作ることに専念できます。これにより新規採用やスケールが容易になります。
  • 新機能を素早く追加(1画面)

    • 最も摩擦の少ない導入方法の一つは、新機能を丸ごとReact Nativeで作ることです。オンボーディングや設定、チャット画面などを既存アプリに追加できます。
  • マイグレーション戦略

    • 老朽化したネイティブコードベースを維持するより、アプリ全体を書き換えるのではなく一部ずつReact Nativeに置き換えることで、徐々に高速な開発サイクルの恩恵を受けられます。

どこから始めるか(概要)

Expoを既存プロジェクトに統合する手順は比較的シンプルです。詳細なコードや手順は“How to add Expo to an existing native app”のドキュメントを参照してください。ここでは要点だけを示します。

  1. 既存アプリプロジェクト内にExpoプロジェクトを作成する

    • コマンド例: npx create-expo-app my-project
  2. プロジェクト構成を整える

    • 標準的なReact Nativeプロジェクトではネイティブコードをandroidiosディレクトリに置きます。方法はプロジェクトによりますが、ディレクトリを作成して既存のプロジェクトを移動するか、カスタムのproject rootを設定することになります。
    • 例: mv /path/to/your/ios-project my-project/ios/
  3. ネイティブプロジェクトの設定

    React Nativeと既存ネイティブコードを接続するために、AndroidとiOSの両方でいくつかの小さな変更を行います。これにより、既存の画面と並行してReact Nativeコードを読み込み・実行できるようになります。

    • Android

      • Gradleファイル: settings.gradle, build.gradle, app/build.gradle, gradle.properties を更新して、React Native Gradle Plugin (RNGP) や必要なプロパティを含めます。
      • AndroidManifest.xml: 必要なパーミッションを追加します(詳細はドキュメント参照)。
      • MainActivity: React Nativeアプリケーションを初期化して、既存のActivity内にビューをレンダリングできるようにします。
      • ReactActivity(または類似の実装): ReactコンポーネントをレンダリングするActivityを作成・表示します。
    • iOS

      • Podfile: React Nativeの依存関係を追加し、pod install を実行します。
      • Xcodeプロジェクト: JavaScriptコードをバンドルするための新しいビルドフェーズを追加します。
      • Info.plist: React Nativeが要求するアプリ設定を構成します。
      • ReactViewController(または類似の実装): React Nativeランタイムを起動しコンポーネントをレンダリングするビューコントローラを作成・表示します。

    これらの変更を行えば、既存のネイティブ画面と並行してReact Nativeコードを実行できます。

  4. アプリをビルドしてMetroバンドラーを起動する

    • ネイティブアプリをビルドしたら、React Nativeディレクトリで次のコマンドを実行してMetroを起動します: npx expo start

オープンソースアプリでの実例

実際のアプリを参考にしたサンプルリポジトリを用意しています。GitHubにある複数のオープンソースアプリへExpoを統合した例をまとめており、AndroidとiOS(UIKitとSwiftUI両方)のサンプルを含みます。

  • リポジトリ: https://github.com/expo/expo-brownfield-examples
  • 例に含まれるアプリ: AntennaPod, IceCubesApp, NetNewsWire, simplenote
  • 各サブモジュールのコミット履歴を参照すると、どのようにしてExpoがアプリに追加されたかがわかります。
  • BlankIOSやBlankAndroidのサブモジュールも参考にできます。

現在の制限と今後の予定

  • 大半のExpoライブラリは追加の変更なしで動作しますが、一部はアプリライフサイクルを監視するための追加設定が必要になることがあります。AndroidおよびiOS向けのライフサイクルリスナー設定については、それぞれのドキュメントを参照してください。
  • expo-dev-client のようなライブラリは現時点でサポート外ですが、次のSDKリリースでのサポート追加に向けて作業中です。
  • サポートされていないライブラリの一覧は次のページで確認できます: https://docs.expo.dev/brownfield/overview/
  • 我々はこの統合を継続的に改善しており、複数のオープンソースアプリでテストを行っています。いくつかの実験的な例は次のリポジトリでも確認できます: https://github.com/gabrieldonadel/expo-brownfield-experiments

まとめ

Expoは追加的に導入できるため、既存のネイティブ投資を維持しつつReact Nativeの利点を段階的に取り入れられます。小さな画面や機能から始めて、徐々に採用範囲を広げるのが現実的でリスクの低いアプローチです。