Skip to content

React Native Environment Setup

Language: JavaScript

The development environment for React Native and Expo projects. This page covers system prerequisites, local development without any cloud account, building without Expo tooling, Metro bundler configuration, and platform-specific setup.

On This Page


Prerequisites

The Superloom client stack uses Expo as the app framework. The Expo path is the primary setup. Building without Expo tooling is documented for teams that need to compile native projects directly.

Expo Path (Primary)

ToolVersionWhy
Node.js24.x or higherJavaScript runtime and package management
npm10.x or higherPackage manager
Expo CLILatest (via npx expo)Project initialization, dev server, build orchestration
Expo GoLatest from App Store / Play StoreOptional. Run JS on a physical device without a native build
WatchmanLatestFile watcher, required by Metro on macOS

Expo CLI ships with the project. No global install is needed. Running npx expo inside a project directory uses the locally pinned version.

Native Build Prerequisites

ToolVersionWhy
Node.js24.x or higherJavaScript runtime
WatchmanLatestFile watcher for Metro
XcodeLatest (macOS only)iOS builds, Simulator, Swift toolchain
CocoaPodsLatestiOS dependency manager (pod install after native dependency changes)
Android StudioLatestAndroid SDK, emulator, build tools
JDK17Gradle build requirement for Android

These tools are required when building native projects directly, whether generated by prebuild or hand-maintained. A prebuild-generated project needs the same toolchain as a hand-maintained one; the difference is who maintains the project files.


Local Development Without an Expo Account

Expo local development requires no account. The following commands work with zero login.

Start the Dev Server

bash
npx expo start

This starts Metro and prints a QR code. The server watches for file changes and hot-reloads on all targets.

Running on a Physical Device

CapabilityCommandAccount
Dev server with QR code over LANnpx expo startNone
Fully offline dev servernpx expo start --offlineNone
Force the Expo Go targetnpx expo start --goNone
Restrict to localhostnpx expo start --localhostNone
Public proxy when LAN is blockednpx expo start --tunnelNone, but needs internet
Local compile and installnpx expo run:ios --deviceNone
Cloud build, over-the-air updateseas build, eas updateRequired

The phone and the computer must be on the same network for the QR code path. --offline prevents the CLI making network requests. Without it, offline support auto-enables when there is no connection, it just takes longer while reachability is probed. --tunnel cannot combine with --offline, because tunneling requires a network connection on both devices. Per Expo's documentation, local compilation is the only way to install a development build on an iPhone without a paid Apple Developer account.

Install Expo Go from the App Store (iOS) or Play Store (Android), open it, and scan the QR code from the terminal. The JavaScript bundle loads on the device over the local network. Expo Go handles web, iOS, and Android. It cannot run custom native modules. When a project includes custom native code, use a dev client instead.

Run on iOS Simulator

bash
npx expo start --ios

Opens the iOS Simulator and loads the project. Requires Xcode installed.

Run on Android Emulator

bash
npx expo start --android

Opens the configured Android emulator and loads the project. Requires Android Studio with an AVD configured.

Run on Web

bash
npx expo start --web

Opens the project in a browser tab. React Native Web maps the RN component API to DOM elements. No emulator or simulator needed.

Dev Client with Prebuild

When a project includes custom native modules (beyond the Expo SDK), Expo Go cannot run it. The dev client replaces Expo Go for this case.

bash
npx expo prebuild          # Generates ios/ and android/ native projects
npx expo run:ios           # Builds and runs on iOS Simulator or device
npx expo run:android       # Builds and runs on Android emulator or device

Prebuild generates native project directories from app.json configuration. Under Continuous Native Generation, ios/ and android/ are added to .gitignore on project creation. Committing them causes EAS and prebuild to skip regeneration, which is the unwanted behavior. Running expo prebuild --clean regenerates them from scratch.

No Expo account is needed for any of these commands.


Building Without Expo Tooling

Expo's documentation deprecates the managed-versus-bare distinction. All Expo projects use Continuous Native Generation. There is no separate "bare" workflow; there are only projects that use Expo's tooling and projects that build the generated native directories directly.

Prebuild Output

npx expo prebuild emits ios/ and android/ directories that are ordinary React Native native projects. These directories build with the platform's own toolchain, with no Expo CLI in the loop:

  • Android: ./gradlew assembleDebug from android/
  • iOS: xcodebuild -workspace *.xcworkspace -scheme <scheme> -configuration Debug -sdk iphonesimulator CODE_SIGNING_ALLOWED=NO from ios/

CODE_SIGNING_ALLOWED=NO removes the Apple Developer account requirement. It proves compilation, not installability.

Maintenance Overhead

ConcernGenerated by prebuildHand-maintained native projects
Native dependency updateexpo prebuild --clean regeneratesManual pod install + Gradle sync
iOS project filesGenerated, gitignored, regenerableHand-maintained
Android project filesGenerated, gitignored, regenerableHand-maintained
OTA updatesAvailable via EAS UpdateNot available without custom infrastructure
Dev clientBuilt by ExpoBuilt manually

Metro Bundler

Metro is the shipping bundler for web, iOS, and Android. The stack decision locks Metro for shipping pipelines. A second bundler is permitted only for a portability harness; see Client Architecture for the full decision.

Configuration

Expo configures Metro automatically. The expo.web.bundler field in app.json selects Metro for web output:

json
{
  "expo": {
    "web": {
      "bundler": "metro"
    }
  }
}

React Native Web and react-dom must be installed for web output. Metro resolves platform files automatically based on extension priority.

Platform-File Resolution

Metro resolves platform-specific files by extension. The priority order:

text
index.ios.js       iOS only
index.android.js   Android only
index.native.js    iOS and Android (coarsest native split)
index.web.js       Web only
index.js           Fallback for all platforms

The coarsest split that works is preferred. Use index.native.js over separate .ios.js and .android.js files when the implementations are identical. See Client Architecture for the platform-file convention.

Cache Clearing

Metro caches transformed modules. When builds behave unexpectedly, clear the cache:

bash
npx expo start --clear

Or delete the cache directly:

bash
rm -rf node_modules/.cache

Platform-Specific Setup

iOS

RequirementSetup
XcodeMac App Store, latest version
SimulatorIncluded with Xcode
Device testingApple Developer account for signing (free for personal device)
CocoaPodssudo gem install cocoapods (native builds only)

A free Apple Developer account allows running on a personal device. Distribution to the App Store requires a paid Apple Developer Program membership.

Android

RequirementSetup
Android StudioDownload from developer.android.com
SDK PlatformInstall via SDK Manager
EmulatorCreate an AVD via AVD Manager
Device testingEnable USB debugging in Developer Options

Android device testing requires no paid account. Enable USB debugging on the device and connect via USB.

Web

RequirementSetup
BrowserAny modern browser (Chrome, Firefox, Safari)
React Native WebInstalled as a project dependency
react-domInstalled as a project dependency

No additional setup is needed for web. Metro serves the bundle and the browser renders it.


Troubleshooting

Metro Port Conflict

Metro uses port 8081 by default. If another process occupies it:

bash
lsof -i :8081       # Find the process
kill -9 <PID>       # Terminate it

Or start Metro on a different port:

bash
npx expo start --port 8082

iOS Pod Issues (Native Build)

If iOS builds fail after adding a native dependency:

bash
cd ios && pod install && cd ..

If pods are corrupted:

bash
cd ios
rm -rf Pods Podfile.lock
pod install
cd ..

Android SDK License Acceptance

If the Android build fails with a license error:

bash
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses

Watchman Issues (macOS)

If Watchman consumes excessive CPU or stops watching files:

bash
watchman shutdown-server
watchman watch-del-all

Metro Cache Corruption

If the bundle has stale modules or phantom errors:

bash
npx expo start --clear
rm -rf node_modules/.cache

Node Modules Out of Sync

If the bundle fails to resolve modules after dependency changes:

bash
rm -rf node_modules
npm install
npx expo start --clear

Further Reading

Released under the MIT License.