正在加载,请稍候…

Expo EAS Build and Deployment: From Development to App Store

Master Expo EAS Build for React Native apps: configure multi-environment builds, implement OTA updates, manage app signing, and automate App Store and Play Store submissions.

Expo EAS Build and Deployment: From Development to App Store

Expo Application Services (EAS) has become the gold standard for React Native build and deployment. EAS Build handles native compilation in the cloud, EAS Submit automates store submissions, and EAS Update enables instant over-the-air updates.

Setting Up EAS

Installation and Initialization

npm install -g eas-cli
eas login
eas init --id your-project-id

eas.json Configuration

{
  "cli": {
    "version": ">= 7.0.0",
    "appVersionSource": "remote"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "env": {
        "APP_ENV": "development",
        "API_URL": "https://api-dev.example.com"
      }
    },
    "staging": {
      "distribution": "internal",
      "env": {
        "APP_ENV": "staging",
        "API_URL": "https://api-staging.example.com"
      },
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": false
      }
    },
    "production": {
      "autoIncrement": true,
      "env": {
        "APP_ENV": "production",
        "API_URL": "https://api.example.com"
      },
      "android": {
        "buildType": "app-bundle"
      }
    }
  },
  "submit": {
    "production": {
      "android": {
        "serviceAccountKeyPath": "./service-account.json",
        "track": "internal"
      },
      "ios": {
        "appleId": "your@apple.com",
        "ascAppId": "1234567890",
        "appleTeamId": "TEAM123"
      }
    }
  }
}

Multi-Environment Configuration

app.config.js with Environment Variables

// app.config.js
const IS_DEV = process.env.APP_ENV === 'development';
const IS_STAGING = process.env.APP_ENV === 'staging';

export default {
  name: IS_DEV ? 'MyApp (Dev)' : IS_STAGING ? 'MyApp (Staging)' : 'MyApp',
  slug: 'my-app',
  version: '1.0.0',
  icon: IS_DEV ? './assets/icon-dev.png' : './assets/icon.png',
  android: {
    package: IS_DEV
      ? 'com.example.myapp.dev'
      : IS_STAGING
      ? 'com.example.myapp.staging'
      : 'com.example.myapp',
  },
  ios: {
    bundleIdentifier: IS_DEV
      ? 'com.example.myapp.dev'
      : IS_STAGING
      ? 'com.example.myapp.staging'
      : 'com.example.myapp',
  },
  extra: {
    apiUrl: process.env.API_URL,
    appEnv: process.env.APP_ENV,
    eas: { projectId: 'your-project-id' },
  },
  updates: {
    url: 'https://u.expo.dev/your-project-id',
  },
  runtimeVersion: {
    policy: 'appVersion',
  },
};

EAS Build Workflow

Building for All Platforms

# Development build
eas build --platform all --profile development

# Staging build
eas build --platform android --profile staging

# Production build
eas build --platform all --profile production --non-interactive

Custom Build Hooks

// eas.json additions
{
  "build": {
    "production": {
      "buildArtifactPaths": ["ios/build/MyApp.ipa"],
      "prebuildCommand": "node scripts/pre-build.js",
      "cache": {
        "key": "my-cache-key-v1",
        "paths": [
          "node_modules",
          "ios/Pods"
        ],
        "disabled": false
      }
    }
  }
}

EAS Update: OTA Updates

Configuration

npx expo install expo-updates
eas update:configure

In your app:

import * as Updates from 'expo-updates';

async function checkForUpdates() {
  if (__DEV__) return;

  try {
    const update = await Updates.checkForUpdateAsync();

    if (update.isAvailable) {
      await Updates.fetchUpdateAsync();

      await Updates.reloadAsync();
    }
  } catch (error) {
    console.error('Update check failed:', error);
  }
}

// In App.tsx
useEffect(() => {
  checkForUpdates();
}, []);

Update Channels and Rollback

# Publish update to staging channel
eas update --channel staging --message "Fix login bug"

# Publish to production
eas update --channel production --message "v1.2.1 hotfix"

# List updates
eas update:list --channel production

# Rollback (republish previous update)
eas update:republish --channel production --group <update-group-id>

Runtime Version Strategy

// eas.json
{
  "build": {
    "production": {
      "channel": "production",
      "runtimeVersion": "1.0.0"
    }
  }
}

App Signing Management

Android Keystore

# EAS manages credentials automatically
eas credentials --platform android

# Or provide your own
eas credentials --platform android --profile production

iOS Certificates and Profiles

# Auto-manage iOS credentials
eas build --platform ios --profile production
# EAS will create/renew certificates automatically

# View credentials
eas credentials --platform ios

CI/CD Integration

GitHub Actions Workflow

# .github/workflows/eas-build.yml
name: EAS Build

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    name: Build and Deploy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Setup EAS
        uses: expo/expo-github-action@v8
        with:
          eas-version: latest
          token: ${{ secrets.EXPO_TOKEN }}

      - name: Build on EAS
        run: eas build --platform all --profile production --non-interactive

      - name: Submit to stores
        if: github.ref == 'refs/heads/main'
        run: eas submit --platform all --profile production --non-interactive

App Store Submission

# Submit after successful build
eas submit --platform ios --latest --profile production

# Submit specific build
eas submit --platform android --id <build-id> --profile production

# Auto-submit after build
eas build --platform all --profile production --auto-submit

Monitoring and Analytics

import * as Updates from 'expo-updates';
import * as Sentry from '@sentry/react-native';

// Track update adoption
Sentry.setTag('update_id', Updates.updateId ?? 'embedded');
Sentry.setTag('runtime_version', Updates.runtimeVersion);
Sentry.setTag('channel', Updates.channel);
Sentry.setTag('app_env', process.env.APP_ENV);

Conclusion

EAS Build and Deploy provides a complete, production-grade CI/CD pipeline for React Native apps. The combination of cloud builds, OTA updates, automated signing, and store submission eliminates most of the operational complexity of mobile deployment. Teams can focus on building features while EAS handles the infrastructure, making it the most efficient path from code to users' devices.