skip to content

In an Expo project, what do npx expo run:ios and npx expo run:android do, and when do you need to run them again?

level: middleimportance: must knowfreq 50%

answer

  1. local native compile and install
  2. prebuild only if the folder is missing
  3. Debug by default, Metro on 8081
  4. --configuration Release, --variant release
  5. rerun only for native changes

basics

~20 s

They compile the native app locally with Xcode or Gradle, install it on a simulator, emulator or device, and start Metro. Run them again only after native changes: a native library, a config plugin, or native app config.

solid answer

~40 s

`npx expo run:ios` and `npx expo run:android` are the local way to build a development build. Each checks for the platform folder and runs prebuild only if it is missing, compiles with Xcode (Debug configuration by default) or Gradle (debug variant by default), installs the app on a simulator, emulator or connected device, and starts Metro on port 8081 unless you pass `--no-bundler`. They need the local toolchain: Xcode on macOS for iOS, the Android SDK for Android. Rerun them after anything native changes, such as installing a library with native code, adding or changing a config plugin, or changing the app name, icon or permissions; for those app config changes, run `npx expo prebuild` first, because an existing folder is not regenerated. JavaScript changes only need Metro.

code

bash · 10 lines
bash
# First build, or after a native change
npx expo run:ios
npx expo run:android --device

# After changing app config or plugins with existing native folders
npx expo prebuild
npx expo run:ios --no-bundler   # a Metro server is already running

# Local Release build of iOS to check production behaviour
npx expo run:ios --configuration Release

go deeper

for a junior

Recall that run:ios and run:android build and install the native app locally and start Metro, and that JavaScript edits do not need them.

for a middle

Explain the steps of one run, the Debug default and main flags, and why an existing native folder is not regenerated.

for a senior

Show how you decide when a rebuild is needed, avoid the stale-folder trap after config changes, and split local runs from shared EAS builds.

for a principal

Decide who on a team builds native binaries locally versus from shared cloud builds, based on toolchain cost and how often native code changes.

## What the commands are for A development build has to be compiled once per native change. Expo offers two ways: in the cloud with EAS Build, or **locally** with `npx expo run:ios` and `npx expo run:android`. The run commands wrap the native toolchains so you do not open Xcode or Android Studio for everyday builds. ## What one run does 1. **Ensures the native project exists**: if `ios/` or `android/` is missing, it runs prebuild for that platform. If the folder exists, it uses it as it is. 2. **Compiles** with Xcode (`--configuration`, default Debug) or Gradle (`--variant`, default debug). 3. **Installs and launches** the app on a simulator, emulator or connected device (`--device` to choose). 4. **Starts Metro** on port 8081 (`--port` to change, `--no-bundler` to skip), so the freshly installed app connects immediately. If `expo-dev-client` is installed, the result is a development build with the launcher; without it, it is a plain Debug build that connects to Metro directly. ## Useful flags | Flag | Command | Effect | |---|---|---| | `--configuration Release` | `run:ios` | Release build (embedded bundle, no dev tools), unsigned for distribution | | `--variant release` | `run:android` | release variant instead of debug | | `--device` | both | pick a simulator, emulator or connected device | | `--no-bundler` | both | do not start Metro, for example when one is already running | | `--no-install` | both | skip installing dependencies such as pods before building | | `--no-build-cache` | both | clear the native build cache first | | `--all-arch` | `run:android` | build every CPU architecture instead of only the target device's | ## When to run them again Rebuild when a **native input** changed: - installing, removing or upgrading a library that contains native code; - adding or changing a **config plugin** or its options; - changing native app config: name, icon, splash, bundle identifier, permissions, URL schemes; - upgrading the Expo SDK. Do **not** rebuild for JavaScript: screens, hooks, routes and styles are served by Metro and applied with Fast Refresh. ## The stale-folder trap Because the run commands prebuild only when a folder is missing, they do not apply app config or plugin changes to an existing `ios/` or `android/`. After such a change, run `npx expo prebuild` (clean by default since SDK 57) and then the run command. A team that forgets this sees "I added the permission but the prompt text is old" bugs that no JavaScript change can fix. ## Local runs versus EAS - **Local**: fastest turnaround for one developer with Xcode or Android Studio installed; iOS needs a Mac. - **EAS**: no local toolchain, iOS builds without owning a Mac, and an installable build that the whole team can share. Many teams use both: EAS for the shared development build everyone installs, local run commands for the developer who is changing native code that day. ## Reading a failed run - **Pod or Gradle errors after adding a library**: the native project may predate the library's plugin; regenerate with prebuild and retry. - **App installs but shows a red error about a missing native module**: the build on the device is older than the JavaScript; confirm the new build actually installed. - **Metro port already in use**: another server is running; use it with `--no-bundler`, or pick a different `--port`. ## What the machine needs The run commands are thin wrappers over the native toolchains, so the machine must have them installed and working: - **iOS**: macOS with Xcode, its command-line tools and a simulator runtime, plus CocoaPods for the pod install that prebuild and the build step perform. - **Android**: the Android SDK and build tools (usually through Android Studio), a JDK, and an emulator or a connected device. - **Both**: Node and the project's dependencies installed. When a developer cannot or does not want to maintain that setup, the same development build can come from EAS instead, and the run commands are simply not used on that machine.

  • You changed an Info.plist permission string in app.json and rebuilt with npx expo run:ios, but the old text still shows; why?
    `run:ios` prebuilds only when `ios/` is missing, so the existing native project was compiled without the new config. Run `npx expo prebuild` to regenerate the folder, then `npx expo run:ios` again.
  • When would you choose an EAS development build over npx expo run:ios?
    When the developer has no Mac or Xcode setup, or when the build must be shared with teammates and testers as an installable app. Local run commands suit one developer iterating on native code with the toolchain installed.

saying these in an interview costs you the question

  • npx expo run:ios regenerates the ios folder on every run
  • Every JavaScript change needs npx expo run:android
  • run:ios builds a Release configuration by default
  • The run commands work for iOS on any operating system
  • A config plugin change applies without any rebuild