Skip to main content

Using Expo vs React Native CLI

1. Understanding Expo Managed Workflow

The Expo Managed Workflow is a streamlined approach to building React Native applications that abstracts away much of the native code complexity. It allows developers to build, deploy, and manage apps using only JavaScript/TypeScript and a minimal amount of native configuration.

Feature Description Status
Native Code Abstraction Expo handles native code and dependencies, reducing boilerplate. NEW
Prebuilt Modules Access to a wide range of pre-built modules (camera, location, etc.) NEW
Deployment Deploy directly to app stores via Expo services or EAS Build. NEW
Development Environment Uses Expo Go app for live reload and debugging. NEW

Example: Setting up an Expo Project

npm install -g @expo/cli
expo init MyExpoApp
cd MyExpoApp
expo start

Key Benefits of Expo Managed Workflow

  • Fast iteration with live reload
  • Reduced boilerplate and configuration
  • Access to Expo SDK features without native setup
  • Easy deployment with EAS Build or Expo Publish
Warning: The Managed Workflow restricts access to some native modules and requires using Expo's tooling for builds.

2. Understanding Bare Workflow

The Bare Workflow in React Native provides direct access to the native platform APIs without the abstraction layer of Expo. It's ideal for developers who need fine-grained control over their app's native functionality.

Aspect Description Notes
Native Modules Direct access to native iOS and Android modules Requires knowledge of platform-specific code
Device APIs Full access to device capabilities (camera, GPS, etc.) May require additional setup and permissions
Build Process Uses Xcode and Android Studio directly More complex setup compared to Expo
Deployment Manual configuration for app stores Requires handling of certificates and provisioning profiles

Example: Bare Workflow Project Structure

my-bare-app/
├── android/
│   ├── app/
│   └── build.gradle
├── ios/
│   ├── MyBareApp.xcodeproj
│   └── AppDelegate.m
├── src/
│   └── App.js
├── package.json
└── babel.config.js
Note: Bare Workflow is recommended for experienced developers who require native features not available in Expo.
Warning: Setting up the Bare Workflow involves more initial configuration and ongoing maintenance compared to using Expo.

3. Using Expo CLI

Expo CLI is a command-line tool that helps you create, build, and manage React Native projects with Expo. It simplifies development by providing a managed workflow that includes pre-built features and tools.

Command Description Usage
expo init Creates a new Expo project expo init MyApp
expo start Starts the development server expo start
expo run:ios Runs the project on iOS simulator expo run:ios
expo run:android Runs the project on Android emulator expo run:android
expo build:ios Builds the iOS app for distribution expo build:ios
expo build:android Builds the Android app for distribution expo build:android

Example: Initializing an Expo Project

expo init MyApp
cd MyApp
expo start
Note: Expo CLI provides a managed workflow where you can use many native features without ejecting to ExpoKit or bare workflow.
Warning: Not all native modules are supported in the managed workflow. If you need to use a specific native module, you may have to eject to the bare workflow.

4. Ejecting from Expo

Expo provides a streamlined development experience, but sometimes you may need to eject to gain access to native modules or customize the build process. Ejecting from Expo allows you to use React Native CLI and native Android/iOS toolchains.

Step Description Action
1 Ensure your project is in a clean state Run git status and commit any changes to avoid losing work.
2 Run the eject command Execute npx expo eject in your project directory.
3 Choose Eject Mode Select between managed or bare mode.
4 Review generated files Check for updated android/ and ios/ directories.
5 Update dependencies Install any missing native dependencies using npx pod install for iOS.
Note: Ejecting is a one-way process. Once ejected, you cannot return to the Expo managed workflow without recreating your project.

Example: Ejecting from Expo

npx expo eject

Post-Eject Considerations

  • Native modules must be installed manually via npm install or yarn add.
  • Builds must be managed through Xcode (iOS) or Android Studio (Android).
  • Expo SDK features become unavailable and must be replaced with native or community alternatives.

5. Using Expo Go App

The Expo Go app is a mobile client that allows you to run Expo projects directly on your iOS or Android device. It's particularly useful for development and testing without needing to build native binaries.

Feature Description Availability
Expo Go Mobile app for running Expo projects Available on iOS and Android
Live Reload Automatically updates the app when code changes are saved Yes, built-in
Development Server Hosts the development server for local projects Yes, via LAN or tunnel

Example: Running an Expo Project on Device

expo start

Scan the QR code with your device's camera to open the project in Expo Go.

Note: Ensure your device and development machine are on the same network for local development.
Warning: Expo Go is not suitable for production builds; it's intended for development and testing only.

6. Configuring app.json

Property Values Description
expo {...} Expo-specific configuration options
name string Display name of the app
slug string Unique identifier for the app on Expo
version string App version (e.g., "1.0.0")
platforms array Supported platforms (e.g., ["ios", "android"])
icon string Path to app icon (PNG or JPG)
splash {...} Splash screen configuration
ios {...} iOS-specific configuration (e.g., bundleIdentifier, buildNumber)
android {...} Android-specific configuration (e.g., package, versionCode)
web {...} Web-specific configuration (e.g., output, favicon)

Example: Basic app.json structure

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "version": "1.0.0",
    "platforms": ["ios", "android"],
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "ios": {
      "buildNumber": "1",
      "bundleIdentifier": "com.myapp"
    },
    "android": {
      "package": "com.myapp",
      "versionCode": 1
    },
    "web": {
      "output": "web",
      "favicon": "./assets/favicon.png"
    }
  }
}

7. Using Expo SDK Features

Expo provides a rich set of SDK features that simplify development in React Native. These features are accessible through the expo package and include utilities for device APIs, UI components, and more.

Feature Description Usage Example Notes
expo-constants Provides access to app and device information. import Constants from 'expo-constants';\n\nconsole.log(Constants.appVersion); Useful for versioning and debugging.
expo-filesystem Provides access to the device's file system. import * as FileSystem from 'expo-file-system';\n\nconst fileUri = await FileSystem.documentDirectory + 'example.txt'; Supports read/write operations.
expo-secure-store Securely stores key-value pairs on the device. import * as SecureStore from 'expo-secure-store';\n\nawait SecureStore.setItemAsync('key', 'value'); Recommended for sensitive data.
expo-camera Provides camera functionality with preview and capture. import { Camera } from 'expo-camera';\n\nconst [permission] = await Camera.requestCameraPermissionsAsync(); Requires runtime permissions.
expo-notifications Handles local and push notifications. import * as Notifications from 'expo-notifications';\n\nNotifications.scheduleNotificationAsync({\n content: { title: 'Hello', body: 'This is a notification' },\n trigger: null,\n}); Supports scheduling and delivery.
Note: Expo SDK features are only available in Expo Go or when the app is built with expo build. They are not accessible in a standard React Native CLI project unless manually integrated.

8. Handling Native Code

Note: When working with React Native, handling native code requires understanding platform-specific implementations and integration strategies.
Platform Native Code Type Description Integration Method
iOS Swift / Objective-C Native iOS development language Use React Native Bridging to integrate Swift/Objective-C code with JavaScript
Android Kotlin / Java Native Android development language Use React Native Bridging to integrate Kotlin/Java code with JavaScript

Example: Adding a Native Module

// Example of a native module in React Native
import { NativeModules } from 'react-native';

const { MyNativeModule } = NativeModules;

// Usage in JavaScript
MyNativeModule.someMethod("parameter");

Example: iOS Native Module Integration

// Swift implementation in iOS
@objc(MyNativeModule)
class MyNativeModule: NSObject {
  @objc
  func someMethod(_ parameter: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    // Implementation logic here
    resolve("Result from native code")
  }
}

Example: Android Native Module Integration

// Java implementation in Android
@ReactModule(name = "MyNativeModule")
public class MyNativeModule extends ReactContextBaseJavaModule {
  @ReactMethod
  public void someMethod(String parameter, Promise promise) {
    // Implementation logic here
    promise.resolve("Result from native code");
  }
}

Native Code Handling Strategies

  • Bridging: Use React Native's bridging to connect native modules with JavaScript
  • Platform-specific APIs: Access platform-specific features using native code
  • Module Registration: Ensure proper registration of native modules in the React Native context

9. Comparing Build Processes

Aspect Expo React Native CLI
Build Environment Cloud-based builds via Expo Build Service Local machine or CI/CD server
Native Code Integration Limited; uses Expo SDK Full control over native modules
Configuration Managed via app.json or app.config.js Manual configuration in android/ and ios/ folders
Deployment Push updates via expo publish Requires submitting to app stores
Build Time Fast, typically under 5 minutes Can take several minutes depending on project size
Platform Support Supports iOS, Android, Web, and Desktop Supports iOS and Android only

Example: Building with Expo

expo build:android
expo build:ios

Example: Building with React Native CLI

cd android
./gradlew assembleRelease

cd ../ios
xcodebuild -workspace MyProject.xcworkspace -scheme MyProject -configuration Release

10. Choosing the Right Workflow

Expo vs React Native CLI

  • Expo: Ideal for rapid prototyping, cross-platform development, and teams wanting to avoid native code setup. Offers a managed workflow with extensive built-in APIs.
  • React Native CLI: Best for teams needing full control over native modules, custom native features, or performance optimization. Requires more initial setup and native development knowledge.
Feature Expo React Native CLI
Workflow Type Managed Unimodules / Bare
Native Module Support Limited (via Expo SDK) Full control
Build Time Slower (managed build) Faster (custom build)
App Size Larger (includes Expo SDK) Smaller (only needed modules)
Development Speed Fast (no native setup) Slower (requires setup)
Platform Support Web, iOS, Android iOS, Android

When to Use Which

  • Choose Expo if:
    • You're building a cross-platform app quickly
    • You want to avoid native code setup
    • You're using many built-in features (camera, location, etc.)
  • Choose React Native CLI if:
    • You need custom native modules
    • Performance is critical
    • You're comfortable with native development

Was this article helpful?