Rork で作ったアプリに react-native-mmkv を追加した瞬間、Expo Go で開けなくなった経験はないでしょうか。スプラッシュ画面のあとに赤い画面が出て「Native module cannot be null」と表示される、あの状態です。
これは Rork や Expo の不具合ではありません。Expo Go は「Expo SDK にあらかじめ含まれているネイティブモジュール」しか動かせない、という設計上の制約です。アプリにネイティブコードを必要とするライブラリを追加した時点で、Expo Go の役目は終わります。次に必要になるのが Expo Dev Client、いわゆる「カスタム開発ビルド」です。
Rork で生成したアプリに Expo Dev Client を導入する具体的な手順と、私が実際にハマったポイントを実例とともに整理しました。最初の1回だけ覚えてしまえば、以後は新しいネイティブモジュールを追加してもストレスなく開発できるようになります。
Expo Go と Expo Dev Client の違いを正確に理解する
混乱しやすいので、最初にこの2つの位置づけを整理しておきます。
Expo Go は Apple App Store / Google Play で配布されている、誰でもダウンロードできる「汎用プレビューアプリ」です。あなたが書いた JavaScript と Expo SDK 標準のネイティブモジュールを実行できますが、サードパーティのネイティブモジュールは入っていません。
Expo Dev Client は、あなたのアプリ専用にビルドした「開発版アプリ」です。中身は本番用ビルドとほぼ同じで、サードパーティのネイティブモジュールも全部入っています。違いは、JavaScript バンドルを Metro 開発サーバーから動的に読み込めること、デバッグメニューが使えることだけです。
つまり Dev Client は「本番ビルドにホットリロード機能を足したもの」と考えてください。一度ビルドしてインストールしてしまえば、その後の JavaScript の変更は通常通りリロードで反映されます。
導入が必要になる典型的なライブラリ
Rork ユーザーがよく追加するライブラリのうち、Expo Go では動かないものを挙げておきます。
react-native-mmkv:高速ローカルストレージreact-native-purchases(RevenueCat):サブスクリプション課金react-native-vision-camera:高機能カメラreact-native-fast-image:画像キャッシュ最適化react-native-keychain:セキュアな認証情報保存@react-native-firebase/*:Firebase ネイティブ SDKreact-native-skia:高度な2Dグラフィックスreact-native-onesignal:プッシュ通知(Rork に OneSignal を組み込むガイド も参照)
これらのいずれかを package.json に入れた瞬間に、Dev Client を作る必要が出てきます。逆に Expo SDK 内蔵のライブラリ(expo-image、expo-secure-store、expo-notifications など)だけで済んでいるうちは、Expo Go で開発を続けられます。
手順1: prebuild の実行と app.json の整理
最初にやるのは Expo の prebuild コマンドの実行です。これは app.json の設定を読み取って、ネイティブプロジェクト(ios/ と android/)を生成する処理です。
# Rork で生成したプロジェクトのルートディレクトリで実行
npx expo prebuild --clean--clean を付けると既存の ios/ と android/ を削除してから再生成します。Rork で作ったばかりのプロジェクトでは初回なので必須ですが、すでにネイティブコードを手で編集している場合は注意してください。
prebuild が完了すると、app.json の expo.ios.bundleIdentifier と expo.android.package が必須になります。Rork のテンプレートには既に入っていることが多いですが、ない場合は次のように追加します。
{
"expo": {
"name": "MyRorkApp",
"slug": "my-rork-app",
"ios": {
"bundleIdentifier": "com.yourcompany.myrorkapp"
},
"android": {
"package": "com.yourcompany.myrorkapp"
}
}
}bundleIdentifier は App Store Connect で予約済みのものと衝突しないよう、自分のドメインを逆向きにした文字列にするのが慣例です。一度本番に出すと変えにくいので、最初に決めてしまうことをおすすめします。
手順2: expo-dev-client のインストールと EAS Build
次に Dev Client 本体を入れます。
# Dev Client ライブラリを追加
npx expo install expo-dev-client
# EAS CLI を使ってクラウドビルド
npm install -g eas-cli
eas login
eas build:configureeas build:configure は対話形式で eas.json を作成します。すでに EAS で何かをビルドしたことがあれば、そのまま使えます。
eas.json に開発ビルド用のプロファイルを追加します。
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal"
},
"production": {}
}
}developmentClient: true が Dev Client 用ビルドであることを示すフラグです。ios.simulator: true を付けると iOS シミュレータ向けのビルドが作れます。実機にインストールしたい場合はこのフラグを外します。
実際にビルドを走らせます。
# iOS シミュレータ向け
eas build --profile development --platform ios
# Android 実機・エミュレータ両対応
eas build --profile development --platform androidクラウドビルドなので Mac がなくても iOS ビルドが作れます。私は地方で作業していて Mac の環境構築が遅れがちなので、これがいちばんありがたい点でした。所要時間は10〜20分ほどで、終わるとダウンロードリンクがメールとターミナルに届きます。
手順3: Dev Client を起動して開発を始める
ビルドした Dev Client をシミュレータや実機にインストールしたら、開発サーバーを起動します。
npx expo start --dev-client--dev-client フラグが重要です。これを付けないと Expo Go 用の開発サーバーが起動して、Dev Client から接続できません。
ターミナルに表示される QR コードを Dev Client アプリで読み取るか、シミュレータの場合はターミナルで i(iOS)または a(Android)を押すと、自動でシミュレータに繋がります。
接続できれば、あとは通常通りの React Native 開発です。コードを保存すれば自動でリロードされ、ネイティブモジュールも全部使えます。
つまずきやすい3つのポイント
1. ネイティブモジュールを追加するたびにリビルドが必要
これが Dev Client で最も誤解されやすい点です。react-native-mmkv を入れた状態でビルドした Dev Client は、react-native-mmkv 用にビルドされています。後から react-native-purchases を追加した場合、その新しいネイティブモジュールは Dev Client にまだ含まれていないので、もう一度 eas build --profile development を走らせる必要があります。
JavaScript の変更だけならリロードで反映されますが、ネイティブモジュールが変わったらリビルド、と覚えてください。
2. EAS のビルド回数制限と料金
EAS Build は無料プランだと月30回までという制限があります(2026年5月時点)。個人開発で同時に複数のアプリを抱えていると意外と早く使い切るので、最初から有料プランを検討しておくと安心です。月額 $19 の Production プランで月2,000分のビルド時間が付いてきます。
毎日のように新しいネイティブモジュールを試す段階では、ローカルビルドという選択肢もあります。
eas build --profile development --platform ios --local--local フラグを付けると、自分の Mac で iOS ビルドを実行できます。Xcode のセットアップは必要ですが、ビルド回数を気にせず試行錯誤できるようになります。
3. EAS Update との関係
EAS Update(OTAアップデート) を使っている場合、Dev Client にもチャンネル設定が必要です。app.json の runtimeVersion を固定し、開発ビルドと本番ビルドでチャンネルを分けてください。
{
"expo": {
"runtimeVersion": "1.0.0",
"updates": {
"url": "https://u.expo.dev/your-project-id",
"requestHeaders": {
"expo-channel-name": "development"
}
}
}
}これを忘れると、Dev Client が本番チャンネルの古い JavaScript バンドルを取りに行ってしまい、「ローカルで直したはずのバグが消えない」という現象が起きます。私は実際にこれで半日溶かしました。
Rork 利用者だからこそ意識したいこと
Rork が AI で生成してくれるコードは、デフォルトで Expo SDK の範囲内に収まるよう設計されています。これは「Expo Go ですぐに動かせる」という体験を最大限にスムーズにするための判断で、初心者にとっては理想的です。
一方で、本格的にアプリをリリースしようとすると、ほぼ確実に Dev Client への移行が必要になります。プッシュ通知の高度な設定、サブスクリプション課金、高速ストレージ、いずれもネイティブモジュールが絡みます。
私自身、Rork で作ったアプリを App Store に出すまでに3回ほどこの壁にぶつかりました。最初は「Rork の AI に頼んだコードがエラーになった」と勘違いして、AI に何度もリトライさせていたのですが、原因は環境側でした。Dev Client の存在を知ったときは、もっと早く教えてほしかったと正直思いました。
なので、Rork で「そろそろ本番リリースを考えよう」と思ったタイミングで、一度 Dev Client への切り替えをセットでやってしまうのが結果的に近道です。App Store Connect への申請手順 や ローカルストレージの使い分け も、Dev Client を前提とした記事になっているので、合わせて読んでおくと迷いが減ります。
うまく動かないときの確認リスト
ここまで全部やっても、起動した瞬間にクラッシュする状態にハマることがあります。原因を深追いする前に、まず次の4つを順番に確認してください。
- ネイティブモジュールを追加した後、本当にリビルドしましたか?
eas build --profile development --platform ios|android - インストールされている Dev Client は最新のものですか? 古いビルドがシミュレータに残ったままになりがちです
- 開発サーバーは
--dev-clientフラグ付きで起動していますか? - EAS Update を使っている場合、Dev Client が見ているチャンネルは正しいですか?
私自身、Dev Client 関連のトラブルの9割はこの4項目のどれかでした。先にこれを潰してから原因調査に入ると、時間の節約になります。
次にやること
ここまでで Dev Client の導入は完了です。次のステップとしては、自分のアプリで本当に必要なネイティブモジュールを1つだけ追加して、ビルドして動かしてみてください。最初は react-native-mmkv のような小さくて副作用の少ないライブラリを選ぶのがおすすめです。動作確認できたら、その経験をベースに RevenueCat やプッシュ通知など、より大きなライブラリへ進んでください。
Dev Client は一度導入してしまえば、以降の開発体験を大きく変えてくれます。Rork のスピード感を保ったまま、本番アプリに必要なすべての機能が使えるようになる、その入口です。
Expo の挙動を腹落ちさせると、トラブル時の切り分けが速くなります。