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
- Local Development Without an Expo Account
- Building Without Expo Tooling
- Metro Bundler
- Platform-Specific Setup
- Troubleshooting
- Further Reading
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)
| Tool | Version | Why |
|---|---|---|
| Node.js | 24.x or higher | JavaScript runtime and package management |
| npm | 10.x or higher | Package manager |
| Expo CLI | Latest (via npx expo) | Project initialization, dev server, build orchestration |
| Expo Go | Latest from App Store / Play Store | Optional. Run JS on a physical device without a native build |
| Watchman | Latest | File 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
| Tool | Version | Why |
|---|---|---|
| Node.js | 24.x or higher | JavaScript runtime |
| Watchman | Latest | File watcher for Metro |
| Xcode | Latest (macOS only) | iOS builds, Simulator, Swift toolchain |
| CocoaPods | Latest | iOS dependency manager (pod install after native dependency changes) |
| Android Studio | Latest | Android SDK, emulator, build tools |
| JDK | 17 | Gradle 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
npx expo startThis starts Metro and prints a QR code. The server watches for file changes and hot-reloads on all targets.
Running on a Physical Device
| Capability | Command | Account |
|---|---|---|
| Dev server with QR code over LAN | npx expo start | None |
| Fully offline dev server | npx expo start --offline | None |
| Force the Expo Go target | npx expo start --go | None |
| Restrict to localhost | npx expo start --localhost | None |
| Public proxy when LAN is blocked | npx expo start --tunnel | None, but needs internet |
| Local compile and install | npx expo run:ios --device | None |
| Cloud build, over-the-air updates | eas build, eas update | Required |
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
npx expo start --iosOpens the iOS Simulator and loads the project. Requires Xcode installed.
Run on Android Emulator
npx expo start --androidOpens the configured Android emulator and loads the project. Requires Android Studio with an AVD configured.
Run on Web
npx expo start --webOpens 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.
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 devicePrebuild 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 assembleDebugfromandroid/ - iOS:
xcodebuild -workspace *.xcworkspace -scheme <scheme> -configuration Debug -sdk iphonesimulator CODE_SIGNING_ALLOWED=NOfromios/
CODE_SIGNING_ALLOWED=NO removes the Apple Developer account requirement. It proves compilation, not installability.
Maintenance Overhead
| Concern | Generated by prebuild | Hand-maintained native projects |
|---|---|---|
| Native dependency update | expo prebuild --clean regenerates | Manual pod install + Gradle sync |
| iOS project files | Generated, gitignored, regenerable | Hand-maintained |
| Android project files | Generated, gitignored, regenerable | Hand-maintained |
| OTA updates | Available via EAS Update | Not available without custom infrastructure |
| Dev client | Built by Expo | Built 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:
{
"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:
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 platformsThe 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:
npx expo start --clearOr delete the cache directly:
rm -rf node_modules/.cachePlatform-Specific Setup
iOS
| Requirement | Setup |
|---|---|
| Xcode | Mac App Store, latest version |
| Simulator | Included with Xcode |
| Device testing | Apple Developer account for signing (free for personal device) |
| CocoaPods | sudo 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
| Requirement | Setup |
|---|---|
| Android Studio | Download from developer.android.com |
| SDK Platform | Install via SDK Manager |
| Emulator | Create an AVD via AVD Manager |
| Device testing | Enable USB debugging in Developer Options |
Android device testing requires no paid account. Enable USB debugging on the device and connect via USB.
Web
| Requirement | Setup |
|---|---|
| Browser | Any modern browser (Chrome, Firefox, Safari) |
| React Native Web | Installed as a project dependency |
| react-dom | Installed 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:
lsof -i :8081 # Find the process
kill -9 <PID> # Terminate itOr start Metro on a different port:
npx expo start --port 8082iOS Pod Issues (Native Build)
If iOS builds fail after adding a native dependency:
cd ios && pod install && cd ..If pods are corrupted:
cd ios
rm -rf Pods Podfile.lock
pod install
cd ..Android SDK License Acceptance
If the Android build fails with a license error:
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licensesWatchman Issues (macOS)
If Watchman consumes excessive CPU or stops watching files:
watchman shutdown-server
watchman watch-del-allMetro Cache Corruption
If the bundle has stale modules or phantom errors:
npx expo start --clear
rm -rf node_modules/.cacheNode Modules Out of Sync
If the bundle fails to resolve modules after dependency changes:
rm -rf node_modules
npm install
npx expo start --clearFurther Reading
- Client Architecture - Stack decision, project layout, bundler-agnostic rule
- Expo Guide - Expo capabilities, adapter pattern, cloud account features
- React Native Testing - Testing conventions for RN and Expo modules
- Client Modules - Module naming taxonomy for framework-tier packages
- Getting Started - Project setup walkthrough