In a bare React Native project, what does npm run ios or npm run android do, and how do you pick an iOS simulator?
answer
- CLI wraps xcodebuild or gradlew
- install and launch on a simulator
- debug app pulls JS from Metro
- --simulator or --udid for iOS
- xcrun simctl list devices
basics
~20 sThe scripts call the React Native CLI's run-ios or run-android, which builds the native app with Xcode or the Gradle wrapper, installs it on a simulator, emulator or device, and launches it; a debug build then loads its JavaScript from Metro.
solid answer
~40 s`npm run ios` and `npm run android` are package scripts for the React Native Community CLI's `run-ios` and `run-android` commands. They compile the **native** app, with Xcode's build system on iOS and the project's `./gradlew` on Android, install the result on an iOS Simulator, an Android emulator or a connected device, and launch it. In the Debug configuration the app fetches its JavaScript from the Metro dev server, started with `npm start`; on the iOS Simulator and in Android debug variants no bundle is even embedded. To choose an iOS simulator, pass `--simulator "iPhone SE (3rd generation)"`, optionally with the iOS version in parentheses, or `--udid` with an identifier from `xcrun simctl list devices`. Rerun these commands only after native changes; JavaScript edits reach the running app through Metro.
code
bash · 5 linesnpm start # Metro, in its own terminal
xcrun simctl list devices # names and UDIDs
npm run ios -- --simulator="iPhone SE (3rd generation)"
npm run ios -- --udid="AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
npm run android # running emulator or devicego deeper
Recall that the run commands build, install and launch the native app, that Metro serves the JavaScript, and the --simulator and --udid flags.
Explain the split between the native build and the Metro bundle, and why Debug and Release builds load JavaScript differently.
Diagnose which stage failed, native build, install or JavaScript load, and keep the team's inner loop fast by avoiding needless native rebuilds.
Plan the device matrix: which checks simulators and emulators cover and when real devices or remote macOS machines are worth the cost.
## What the scripts are A bare React Native project's `package.json` defines `ios` and `android` scripts that call the **React Native Community CLI** commands `run-ios` and `run-android`. They are convenience wrappers around the native toolchains: 1. **Build** the native app: Xcode's build system for the iOS project, or the Gradle wrapper (`./gradlew`) for the Android project. 2. **Install** the built app on a target: an iOS Simulator, an Android emulator, or a connected device. 3. **Launch** it. Because they build native code, they are the slow part of the loop, and they need the toolchains in place: Xcode and pods on iOS, the JDK, Android SDK and wrapper on Android. ## Where the JavaScript comes from The native build and the JavaScript are separate in development. **Metro** is React Native's JavaScript bundler; its dev server, started with `npm start`, serves the bundle over HTTP. A **Debug** build of the app connects to Metro on launch and downloads the bundle; for the iOS Simulator and for Android's debug variants the build skips embedding a bundle altogether (an iOS Debug build for a physical device still embeds one as a fallback). That is why: - editing a component does not require `npm run ios` again; Metro rebuilds and Fast Refresh updates the running app; - an error screen saying the app cannot connect to the development server means the native app is fine but Metro is not reachable; - a **Release** build is different: it embeds a pre-built bundle and needs no Metro. Rerun the native command only when native code or configuration changes: a new native library, a Podfile or Gradle change, an app icon, a permission string. ## Simulators and emulators | | iOS Simulator | Android emulator | |---|---|---| | Host OS | macOS only, ships with Xcode | macOS, Windows, Linux | | Created in | Xcode, Settings, Platforms | Android Studio's AVD Manager | | What it runs | a Mac build of the app for the simulator | an Android system image | | Listed by | `xcrun simctl list devices` | Android Studio or the SDK tools | Two consequences interviewers like to probe: - You cannot build or run the iOS app on Windows or Linux, because Xcode only runs on macOS; the React Native setup guides for those systems cover Android only. - The Simulator is fast but does not reproduce everything a phone does; hardware-dependent features still need a real device. ## Targeting a specific iOS simulator The CLI picks a default simulator. To choose one: - `npm run ios -- --simulator="iPhone SE (3rd generation)"` selects by device name, exactly as Xcode lists it; - adding the OS version, `--simulator="iPhone 14 Pro (16.0)"`, disambiguates when several iOS runtimes are installed; - `npm run ios -- --udid="<UDID>"` selects one exact simulator by the identifier `xcrun simctl list devices` prints. With npm, the extra `--` passes the flags through to the script; Yarn forwards them directly (`yarn ios --simulator "…"`). On Android, `run-android` installs on the running emulator or the attached device, so starting the right emulator first is the usual way to choose. ## Common first-run failures - **iOS**: pods not installed, or an Xcode below React Native's minimum, fails the build before launch. - **Android**: no emulator running and no device attached, a missing SDK platform, or a wrapper without execute permission. - **Both**: the app launches but shows a connection error because Metro is not running. Knowing which of the three stages failed, build, install or JavaScript load, points straight at the fix. ## Why the split matters day to day The native build is slow and the JavaScript loop is fast, so a productive React Native workflow keeps them apart. Run `npm run ios` or `npm run android` once to put a Debug build on the simulator or emulator, keep Metro running in its own terminal, and iterate on components with Fast Refresh. Rebuild natively only when something native changed. Teams that rerun the native command after every edit spend minutes per change on work Metro would have done in a second, and teams that never rebuild after adding a native library chase "module not found" errors that a single native build fixes.
- In React Native, why does a component edit not need npm run ios again?A Debug build loads its JavaScript from the Metro dev server. Metro rebuilds changed modules and Fast Refresh pushes them into the running app, so only native changes, such as a new native library or a Podfile or Gradle edit, need a new native build.
- Why can't a React Native developer on Windows run the iOS app locally?Building an iOS app needs Xcode, which only runs on macOS, and the iOS Simulator ships with Xcode. The React Native setup guides for Windows and Linux therefore cover Android only; iOS builds need a Mac or a remote macOS build machine.
saying these in an interview costs you the question
- npm run ios must be rerun after every JavaScript change
- A Debug build for the iOS Simulator carries its own embedded JS bundle
- The iOS Simulator can run on Windows with the right plugin
- run-android compiles JavaScript with Gradle instead of Metro