Skip to content
·8 min read

I Switched From React Native CLI to Expo EAS — Here's What Changed (and What Didn't)

Expo used to be the training wheels. After EAS Build, it's the fastest way to ship native React Native apps. Here's the workflow I use for client work in 2026.

React NativeExpoEASMobileCI/CD

For years I shipped React Native apps with the bare CLI workflow. I maintained native iOS and Android projects, manually bumped versions in Xcode and Android Studio, managed signing certificates in the Apple Developer portal, and ran fastlane scripts I wrote once and was afraid to touch.

In 2023 I switched to Expo EAS. I am not going back. Here is what changed, what did not, and why this is now my default for client work.

What "Expo" actually means in 2026

The mental model most developers have is stuck in 2019. Expo used to mean:

  • A managed sandbox where you cannot add native code
  • Build through Expo's servers only
  • No custom native modules
  • QR-code preview for development

That Expo is gone. Modern Expo is:

  • A set of dev tools and SDKs
  • Prebuild to generate native iOS and Android projects locally
  • Config plugins to add native modules declaratively
  • EAS Build for cloud builds
  • EAS Update for OTA JS updates
  • A development server with Fast Refresh and better error overlay

The training wheels came off. The tools stayed.

The workflow I use

Every new client project follows the same five steps.

1. Bootstrap with create-expo-app

npx create-expo-app@latest my-app -t tabs
cd my-app

I get a TypeScript project, file-based routing with expo-router, a working tabs layout, and a dev server that runs in the Expo Go app or a custom dev client.

2. Add native modules with config plugins

Most popular libraries now ship Expo config plugins. Add them in app.json:

{
  "expo": {
    "plugins": [
      "expo-router",
      "expo-secure-store",
      "react-native-maps",
      [
        "expo-camera",
        { "cameraPermissionText": "We use the camera to scan barcodes." }
      ],
      [
        "expo-notifications",
        { "icon": "./assets/notif-icon.png" }
      ]
    ]
  }
}

Run npx expo prebuild to generate the ios and android folders. Compile and run to verify everything works. If you ever need to eject, those folders are right there — you are not locked in.

3. Configure EAS Build

Install the CLI and configure:

npm install -g eas-cli
eas login
eas build:configure

This generates eas.json:

{
  "cli": { "version": ">= 5.0.0" },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": { "simulator": true }
    },
    "preview": {
      "distribution": "internal",
      "android": { "buildType": "apk" }
    },
    "production": {
      "autoIncrement": true,
      "android": { "buildType": "app-bundle" }
    }
  },
  "submit": {
    "production": {
      "ios": { "appleId": "you@example.com" },
      "android": { "serviceAccountKeyPath": "./play-key.json" }
    }
  }
}

Then:

eas build --platform ios --profile production
eas submit --platform ios --latest

EAS handles credentials. On the first iOS build, it asks whether to let Expo manage your signing. Say yes unless your client has a specific reason to manage them manually. The first build takes 15-20 minutes; subsequent builds are faster due to caching.

4. Wire up EAS Update for OTA JS updates

OTA updates let you push JavaScript-only changes without App Store review. Bug fixes, copy tweaks, small UI adjustments.

eas update:configure

In app.json:

{
  "expo": {
    "updates": {
      "url": "https://u.expo.dev/your-project-id"
    },
    "runtimeVersion": { "policy": "appVersion" }
  }
}

Push an update:

eas update --branch production --message "Fix: crash on Android 14 on cold start"

Users get the update next time they open the app, after the JS bundle downloads in the background. Rollback is eas update --branch production --revert.

Use OTA for fixes that touch only JavaScript. Native module updates require a full store release.

5. Set up internal distribution for QA

Build a preview profile for testers:

eas build --profile preview --platform all

iOS testers get an ad-hoc IPA via TestFlight (internal testing, no review needed) or a direct install link. Android testers get an APK they can sideload. Use this for every QA cycle instead of waiting for TestFlight review.

What still requires the bare workflow

EAS is not magic. You still need to eject or maintain native code when:

  • You integrate a third-party SDK with no config plugin (some payment SDKs, some BLE libraries)
  • You need to modify native code in ways plugins cannot express
  • You are porting an existing bare-workflow app and the migration cost is too high

For 90 percent of new client work, Expo is faster. For the remaining 10 percent, the bare workflow is still there.

What changed after I switched

Concrete differences on my last three client projects:

  • Build setup: 2 days → 30 minutes. No more wrestling with CocoaPods versions, no more Android NDK setup. EAS handles it.
  • First TestFlight build: 3 days → 1 day. EAS handles signing. I push code, the build runs in the cloud, TestFlight gets the artifact.
  • OTA bug fixes: 0 → ~3 per release cycle. Small bugs that would have waited for the next store release now ship same-day.
  • Onboarding new developers: faster. The Expo tooling is opinionated, so the "how do I run this" question has one answer.

What did NOT change

  • React Native itself is the same runtime. Performance, debugging, and the rest of the stack are unchanged.
  • You still need an Apple Developer account ($99/year) and a Google Play account ($25 once).
  • App Store and Play Store review still takes hours to days. OTA updates do not replace store releases for new features.
  • Native bugs are still native bugs. A crash in a Swift dependency still requires rebuilding the native project.

Expo in 2026 is not the Expo of 2019. It is the fastest path to a production React Native app, and the escape hatch is right there if you need it.

Want help migrating to Expo EAS?

I migrate React Native CLI apps to Expo EAS for clients, and start new projects on Expo from day one. Let's talk.

Frequently Asked Questions

Is Expo EAS Build free to use?

EAS Build has a free tier with 15 iOS and 15 Android builds per month. For a solo developer or small team this is usually enough. Paid tiers add build minutes, priority queues, and shared credentials for teams.

Can I add any native module to Expo?

Yes, with config plugins. Most popular libraries ship with plugins. If a library has no plugin, you can write one or run prebuild and modify the native projects directly. The bare workflow is always available as an escape hatch.

What is EAS Update?

EAS Update is Expo's OTA (over-the-air) update service. It pushes JavaScript-only changes to users without going through App Store review. Use it for bug fixes, copy changes, and small UI updates. Native code changes still require a full store release.

Should I use Expo or React Native CLI in 2026?

Use Expo unless you have a specific reason not to. EAS Build handles native compilation in the cloud, config plugins let you add native modules without ejecting, and OTA updates are built in. The bare workflow is still useful for teams with existing native code or complex native integrations.