DEV Community

Cover image for Build iOS and Android Apps Without a Mac Using EAS
Farukh Saifi
Farukh Saifi

Posted on Originally published at farukh.me

Build iOS and Android Apps Without a Mac Using EAS

Building cross-platform apps with React Native used to hit an immediate hardware bottleneck: if you didn't own a physical Mac, compiling an iOS .ipa binary was virtually impossible without brittle hackintoshes or expensive rented cloud desktops.

Expo Application Services (EAS) solves this friction point. Through remote cloud workers, EAS Build packages native binaries for both operating systems directly from your terminal, regardless of your local machine. Coupled with EAS Update, you can fix production bugs instantly via Over-The-Air (OTA) runtime patches without waiting for App Store or Google Play reviews.

Here is how to set up both workflows from scratch using EAS's generous free tier.


1. Prerequisites and Installation

Ensure you have Node.js installed alongside a standard React Native or Expo project. Install the EAS CLI globally:

npm install -g eas-cli
Enter fullscreen mode Exit fullscreen mode

Log in or register an account on Expo:

eas login
Enter fullscreen mode Exit fullscreen mode

Navigate to your project root and link it to your EAS account:

eas init
Enter fullscreen mode Exit fullscreen mode

This creates an association in your app.json with an EAS project ID.


2. Configuring Cloud Builds with eas.json

EAS configuration lives in an eas.json file at the root of your project. Run the setup generator:

eas build:configure
Enter fullscreen mode Exit fullscreen mode

This generates a boilerplate file. Modify your eas.json to define realistic development, preview, and production profiles:

{
  "cli": {
    "version": ">= 12.0.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": true
      }
    },
    "production": {
      "autoIncrement": true
    }
  },
  "submit": {
    "production": {}
  }
}
Enter fullscreen mode Exit fullscreen mode

Key insight: By default, Android builds produce an .aab (Android App Bundle) designed for the Play Store. Setting "buildType": "apk" in your preview profile outputs a standalone .apk file that you can install directly on test devices via USB or browser download.


3. Triggering Cloud Builds (No Mac Required)

To build a native iOS binary without running Xcode locally, invoke:

eas build --platform ios --profile preview
Enter fullscreen mode Exit fullscreen mode

EAS handles the entire code signing workflow interactively:

  1. If you don't have an iOS Distribution Certificate or Provisioning Profile, EAS prompts to log in to your Apple Developer account.
  2. EAS generates and stores the certificates securely in Expo's cloud vault.
  3. The project bundles, uploads to an isolated macOS runner, runs native compilation, and returns a download link for your .ipa or simulator tarball.

For an installable Android APK:

eas build --platform android --profile preview
Enter fullscreen mode Exit fullscreen mode

EAS can automatically generate and manage your Android keystore credentials, taking the friction out of native certificate handling.


4. Bypassing Store Reviews with EAS Update (OTA)

Binary builds are required when adding new native dependencies or editing app permissions. However, if your changes are limited to JavaScript, TypeScript, or asset updates (e.g., UI tweaks, logic bug fixes), building a full binary is unnecessary.

Initialize EAS Update in your project:

eas update:configure
Enter fullscreen mode Exit fullscreen mode

Verify that app.json includes the runtime configuration:

{
  "expo": {
    "updates": {
      "url": "https://u.expo.dev/<YOUR_PROJECT_ID>"
    },
    "runtimeVersion": {
      "policy": "appVersion"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Pushing an Instant Hotfix

When a bug occurs in production, patch your code and deploy directly to user devices:

eas update --branch production --message "Hotfix: resolve checkout crash"
Enter fullscreen mode Exit fullscreen mode

The update compiles the JS bundle and assets, syncs them to Expo's CDN, and marks them for distribution. The next time users open the application, the new bundle downloads silently in the background and applies on the subsequent launch.


5. Staying Efficient on the Free Tier

Expo's free tier provides 30 build credits per month across Android and iOS, with priority queues reserved for paid tiers. Optimize your monthly usage with these practices:

  • Use local development clients: Run npx expo start for standard iteration instead of triggering a new build for every change.
  • Rely on EAS Update for JS changes: Never spend a build credit on a UI color change, typo, or JavaScript logic tweak.
  • Use the ios.simulator flag: iOS simulator builds finish faster and don't require an active paid Apple Developer account to test on macOS emulators.

EAS transforms mobile development from a heavy local infrastructure challenge into a clean command-line operation.

Top comments (0)