Badal Saibofrontend / ui / ux

Understanding Expo for RN CLI devs

1. expo-dev-client

Whenever you're initializing a new Expo app (npx create-expo-app), you're basically initializing an Expo Go project.
Expo Go is a simplified version of React Native, great for quick prototyping, but limited when you need custom native modules.

If you're coming from React Native CLI, it’s best to switch to an Expo development build early on.
Once you understand this difference, you’re halfway to mastering Expo.

To convert your Expo Go project into a development build, install expo-dev-client:

npx expo install expo-dev-client

This gives you your own Expo Go, built with your app’s native modules included.


2. expo run:<ios/android>

You might notice there are no /ios or /android directories when starting with Expo Go.
That’s because Expo Go doesn’t expose native projects, it just runs your JavaScript bundle inside its own app.

Running either command below will generate those native directories for you and build a development client:

expo run:ios

or

expo run:android

After generation, Expo will install it on your simulator or device.


3. expo prebuild

Whenever you run:

npx expo prebuild

Expo takes your configuration from app.json or app.config.js and generates the underlying native projects (/ios and /android).

prebuild doesn’t automatically install expo-dev-client; it only creates the native folders and syncs configuration.
If you want to retain the Expo developer experience (QR codes, live reload, dev menu, etc.), you’ll still need expo-dev-client.

Without it, your app runs like a regular React Native build, without any Expo features attached.

When you run expo prebuild, it automatically updates your package.json scripts. It replaces expo start --android and expo start --ios with expo run:android and expo run:ios.[1]


4. What does expo-dev-client actually do?

It’s essentially your own version of Expo Go, tailored for your app.
While the stock Expo Go can’t load custom native modules (VisionCamera, Reanimated etc.), your dev client can, because it’s compiled with your code baked in.

With expo-dev-client:

  • You still get the Metro bundler and developer menu.
  • You can scan QR codes again (with your app, not Expo Go).
  • You can install any native module you want.

Without it:

  • You’re running a normal React Native build wihout dev menu and live reloading.

5. TL;DR

StageDescriptionTypical Command
Expo GoNo native code, everything runs inside the Expo Go appexpo start --android
Expo Dev ClientYour own Expo Go with native modules supportexpo run:android
Bare / CLI StylePure native build, no Expo runtimenpx expo prebuild && expo run:android

6. Final Words

Just like you, I always resisted migrating to Expo, but it's good to sit for a day and understand things. Things like CNG are great for longer maintainence of a RN project. Currenlty manually upgrading the ios and android folder when upgrading RN versions are such a pain. With this we can avoid these things, which massively improves upgradation DX.

References

  1. https://docs.expo.dev/workflow/continuous-native-generation/#side-effects