正在加载,请稍候…

Expo EAS 构建与部署:从开发到应用商店

掌握 Expo EAS Build 为 React Native 应用配置多环境构建、实现 OTA 更新、管理应用签名并自动化 App Store 和 Play

Expo EAS Build and Deployment: From Development to App Store

Expo EAS 构建与部署:从开发到应用商店

Expo Application Services (EAS) 已成为 React Native 构建和部署的黄金标准。EAS Build 处理云端原生编译,EAS Submit 自动化商店提交,EAS Update 实现即时空中更新。

设置 EAS

Expo EAS Build and Deployment: From Development to App Store illustration

安装与初始化

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

eas.json 配置

{
  "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"
      }
    }
  }
}

多环境配置

使用环境变量的 app.config.js

// 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 工作流

构建所有平台

# 开发构建
eas build --platform all --profile development

# 预发布构建
eas build --platform android --profile staging

# 生产构建
eas build --platform all --profile production --non-interactive

Expo EAS Build and Deployment: From Development to App Store illustration

自定义构建钩子

// eas.json 附加配置
{
  "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 更新

配置

npx expo install expo-updates
eas update:configure

在应用中:

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);
  }
}

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

更新频道与回滚

# 发布更新到 staging 频道
eas update --channel staging --message "修复登录错误"

# 发布到生产环境
eas update --channel production --message "v1.2.1 热修复"

# 列出更新
eas update:list --channel production

# 回滚(重新发布之前的更新)
eas update:republish --channel production --group <update-group-id>

运行时版本策略

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

应用签名管理

Expo EAS Build and Deployment: From Development to App Store illustration

Android 密钥库

# EAS 自动管理凭据
eas credentials --platform android

# 或提供自己的凭据
eas credentials --platform android --profile production

iOS 证书和配置文件

# 自动管理 iOS 凭据
eas build --platform ios --profile production
# EAS 会自动创建/更新证书

# 查看凭据
eas credentials --platform ios

CI/CD 集成

GitHub Actions 工作流

# .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

应用商店提交

# 构建成功后提交
eas submit --platform ios --latest --profile production

# 提交特定构建
eas submit --platform android --id <build-id> --profile production

# 构建后自动提交
eas build --platform all --profile production --auto-submit

监控与分析

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

// 跟踪更新采用情况
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);

结论

EAS Build 和 Deploy 为 React Native 应用提供了完整的、生产级的 CI/CD 管道。云端构建、OTA 更新、自动签名和商店提交的结合,消除了移动部署的大部分操作复杂性。团队可以专注于构建功能,而 EAS 处理基础设施,使其成为从代码到用户设备的最有效路径。