React Native OTA-Updates mit EAS Update: die CodePush-Alternative
AI generated
RN
native
React Native · Expo · EAS Update · OTA
React Native OTA-Updates mit EAS Update
die praxistaugliche CodePush-Alternative

EAS Update liefert JavaScript-Bundle- und Asset-Updates direkt an installierte React-Native- und Expo-Apps aus, ganz ohne neuen App-Store- oder Play-Store-Review-Zyklus. Wer bisher CodePush genutzt hat, findet in EAS Update den technisch konsequenten Nachfolger: mit Channels, Branches, Runtime Versions, gestuften Rollouts und schnellen Rollbacks als fest eingebaute Bausteine.

18 Min. Lesezeit EAS Update · Channels · Branches · Runtime Versions · Rollouts Expo SDK 51+ · expo-updates

1. Warum EAS Update OTA-Updates für React Native und Expo unverzichtbar macht

Ein klassisches Problem in jeder React-Native-App: Ein kleiner JavaScript-Bug schleicht sich in ein Release, etwa ein falscher Feldname in der Checkout-Logik oder ein Crash beim Öffnen eines bestimmten Screens. Ohne OTA-Mechanismus bleibt nur der reguläre Weg über den Store: neue Build-Nummer, Einreichung bei Apple und Google, Warten auf den Review, und erst danach beginnt der langsame Rollout an die Nutzer. Bei Apple kann dieser Review-Zyklus von wenigen Stunden bis zu mehreren Tagen dauern, bei kritischen Bugs ist das inakzeptabel lange. Genau hier setzt EAS Update an: Es liefert ein aktualisiertes JavaScript-Bundle samt Assets direkt an bereits installierte Apps aus, ohne dass ein neuer Store-Review nötig ist.

Technisch macht EAS Update nichts Mystisches: Metro baut ein neues JS-Bundle, dieses wird zusammen mit den geänderten Assets (Bilder, Fonts, JSON) auf die Expo-Update-Server hochgeladen und dort als Manifest hinterlegt. Die App prüft beim Start oder bei einem expliziten Aufruf, ob ein neueres Manifest für ihren Channel existiert, lädt das zugehörige Bundle herunter und wendet es beim nächsten Neustart an. Der native Anteil der App, also der kompilierte iOS- und Android-Code, bleibt dabei vollständig unverändert. OTA bedeutet hier ausdrücklich: nur JavaScript und Assets, keine native Binärdatei.

Für Teams, die React Native produktiv betreiben, ist das ein enormer Unterschied in der Reaktionsfähigkeit. Ein kritischer Bugfix, der in der klassischen Store-Pipeline Tage braucht, lässt sich über EAS Update in wenigen Minuten an alle betroffenen Nutzer ausliefern. Das gilt für Textfehler, kaputte API-Aufrufe, defekte Business-Logik und Layout-Probleme gleichermaßen, solange kein neuer nativer Code notwendig ist. Wer aus dem CodePush-Ökosystem kommt, erkennt das Grundprinzip sofort wieder, findet in EAS Update aber ein deutlich durchdachteres Modell aus Channels, Branches und Runtime Versions vor.

2. Channels, Branches und Runtime Versions: wie das Modell zusammenspielt

Das Herzstück von EAS Update ist ein dreistufiges Modell, das auf den ersten Blick abstrakt wirkt, in der Praxis aber genau die Probleme löst, an denen einfachere OTA-Lösungen wie CodePush oft gescheitert sind. Ein Branch ist ein benannter Update-Strang, vergleichbar mit einem Git-Branch, zum Beispiel production oder staging. Jede Veröffentlichung mit eas update landet auf genau einem Branch. Ein Channel ist dagegen eine Ebene der Indirektion: Er wird zur Build-Zeit fest in die App einkompiliert und bestimmt, welchen Branch die App zur Laufzeit abfragt. Die Zuordnung Channel-zu-Branch liegt in der EAS-Konfiguration und kann jederzeit geändert werden, ohne dass ein neuer nativer Build nötig wäre.

Diese Indirektion ist der eigentliche Clou: Läuft etwas schief auf dem production-Branch, kann man den production-Channel innerhalb von Sekunden auf einen anderen, bekannt guten Branch umbiegen, ganz ohne neue App-Store-Einreichung. Ergänzt wird das Modell durch die Runtime Version: Sie beschreibt, welche native API-Oberfläche ein bestimmter App-Build bereitstellt. Jedes über EAS Update veröffentlichte JS-Bundle trägt ebenfalls eine Runtime Version. Nur wenn Runtime Version der installierten App und Runtime Version des Updates exakt übereinstimmen, wird das Update überhaupt als kompatibel erkannt und heruntergeladen.

Dieser Abgleich verhindert genau das Szenario, das bei naiven OTA-Ansätzen zu Abstürzen führt: Ein JS-Update referenziert ein natives Modul, das in einem älteren, noch installierten Binary gar nicht existiert. Ohne Runtime-Version-Prüfung würde die App beim Aufruf dieses Moduls abstürzen. Mit korrekt konfigurierter Runtime Version bekommt ein altes Binary schlicht kein inkompatibles Update angeboten, es bleibt so lange auf seiner letzten kompatiblen Version, bis der Nutzer ein reguläres Store-Update mit neuem nativen Code installiert. Die Runtime-Version-Policy wird in app.json oder app.config.js festgelegt, üblicherweise als appVersion-Policy, die die Runtime Version automatisch aus der App-Versionsnummer ableitet.


{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "version": "3.4.0",
    "runtimeVersion": {
      "policy": "appVersion"
    },
    "updates": {
      "url": "https://u.expo.dev/00000000-0000-0000-0000-000000000000",
      "checkAutomatically": "ON_LOAD",
      "fallbackToCacheTimeout": 0
    },
    "ios": { "buildNumber": "17" },
    "android": { "versionCode": 17 }
  }
}

3. eas update CLI: Updates veröffentlichen

Der tägliche Umgang mit EAS Update läuft fast vollständig über das eas update-CLI-Kommando. Der einfachste Aufruf veröffentlicht das aktuelle JS-Bundle auf einem bestimmten Channel, inklusive einer Beschreibung, die später im Dashboard und in eas update:list sichtbar ist. Alternativ kann direkt an einen Branch veröffentlicht werden, was in Teams mit mehreren parallelen Feature-Branches sinnvoll ist, bevor eine Zuordnung zu einem Channel überhaupt existiert. Der Parameter --auto übernimmt automatisch den Namen des aktuellen Git-Branches als Update-Branch, was gerade in CI-Pipelines viele manuelle Schritte spart.

Vor jedem eas update-Aufruf baut die CLI das JS-Bundle lokal oder in der Cloud, berechnet die Runtime Version anhand der konfigurierten Policy und lädt Bundle sowie geänderte Assets auf die Expo-Server hoch. Wichtig für React Native-Teams: Jedes veröffentlichte Update bekommt eine eindeutige Group-ID, über die sich einzelne Updates später gezielt inspizieren, erneut veröffentlichen (republish) oder für einen Rollback referenzieren lassen. Das Kommando eas update:configure richtet die initiale Channel-zu-Branch-Zuordnung interaktiv ein und sollte bei jedem neuen Projekt einmalig ausgeführt werden.


#!/usr/bin/env bash
# Publish a new OTA update to the "production" channel
# The channel routes to whichever branch is currently mapped to it
eas update --channel production --message "Fix checkout crash on iOS 18.1"

# Publish directly to a named branch (channel mapping happens separately)
eas update --branch production --message "Hotfix: null pointer in cart reducer"

# Let EAS auto-detect the branch name from the current git branch
eas update --auto

# List recent updates on a branch, including runtime version and group id
eas update:list --branch production

# Inspect a single update in detail (manifest, runtime version, assets)
eas update:view <update-group-id>

# Configure channel-to-branch mapping interactively
eas update:configure

4. eas.json konfigurieren: Build-Profile und Channel-Mapping

Die Datei eas.json ist der zentrale Konfigurationsort für sowohl EAS Build als auch EAS Update. Für OTA-Updates relevant ist vor allem das Feld channel innerhalb jedes Build-Profils: Es legt fest, mit welchem Channel ein Build fest verdrahtet wird, sobald er auf iOS oder Android installiert ist. Ein Build mit Profil production und Channel production fragt zur Laufzeit ausschließlich Updates ab, die auf den aktuell an diesen Channel gemappten Branch veröffentlicht wurden. Ein separates staging-Profil mit eigenem Channel erlaubt internen Testern, neue OTA-Updates zu sehen, bevor sie überhaupt an den production-Channel gehen.

Diese Trennung ist in der Praxis der Unterschied zwischen einem kontrollierten Rollout-Prozess und einem riskanten Blindflug. Ein Team kann ein OTA-Update zunächst ausschließlich über den staging-Channel an eine interne TestFlight- oder Internal-Testing-Gruppe ausliefern, dort verifizieren, dass keine Regressionen auftreten, und erst danach dieselbe Update-Group auf den production-Channel übertragen. So bleibt React Native mit EAS Update auch bei häufigen Releases beherrschbar, weil jeder Channel eine klare, isolierte Zielgruppe hat.


{
  "cli": {
    "version": ">= 12.0.0",
    "appVersionSource": "remote"
  },
  "build": {
    "production": {
      "channel": "production",
      "autoIncrement": true
    },
    "staging": {
      "channel": "staging",
      "distribution": "internal"
    }
  },
  "submit": {
    "production": {}
  }
}

5. Updates.checkForUpdateAsync und fetchUpdateAsync im App-Code

Auf App-Seite übernimmt die Bibliothek expo-updates die eigentliche Update-Logik. Zwei Funktionen stehen im Mittelpunkt: Updates.checkForUpdateAsync() fragt beim Update-Server nach, ob für den aktuellen Channel ein neueres, kompatibles Manifest existiert, ohne bereits etwas herunterzuladen. Ist ein Update verfügbar, lädt Updates.fetchUpdateAsync() Bundle und Assets im Hintergrund herunter. Das Update wird dabei nicht sofort aktiv, sondern erst nach einem Updates.reloadAsync() oder dem nächsten regulären App-Start angewendet, damit laufende Nutzersitzungen nicht mitten in der Interaktion unterbrochen werden.

Die Konfiguration checkAutomatically: "ON_LOAD" in app.json sorgt dafür, dass expo-updates bereits beim App-Start selbstständig nach einem Update sucht und es im Hintergrund lädt. Für eine bessere UX kombinieren viele Teams das mit einem manuellen Check, etwa wenn die App aus dem Hintergrund zurückkehrt, und zeigen dem Nutzer einen Hinweis an, statt die App ohne Vorwarnung neu zu starten. Wichtig ist der Guard gegen den Entwicklungsmodus: In __DEV__ liefert expo-updates grundsätzlich keine echten Updates, ein Check würde dort ins Leere laufen und sollte deshalb übersprungen werden.

Fehlerbehandlung ist bei OTA-Checks Pflicht, nicht Kür: Ein Nutzer ohne Netzverbindung darf niemals eine Fehlermeldung sehen, nur weil EAS Update gerade nicht erreichbar war. Netzwerkfehler bei checkForUpdateAsync() oder fetchUpdateAsync() sollten daher stillschweigend abgefangen werden, die App läuft in diesem Fall einfach mit der aktuell installierten Version weiter.


import * as Updates from "expo-updates";
import { Alert } from "react-native";

// Manual update check, e.g. triggered when the app returns to the
// foreground, or from a "Check for updates" button in settings
export async function checkForOtaUpdate() {
  if (__DEV__) {
    // Never check for updates in development, only in built binaries
    return;
  }

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

    if (!update.isAvailable) {
      return;
    }

    // Download the new JS bundle and assets in the background
    const result = await Updates.fetchUpdateAsync();

    if (result.isNew) {
      Alert.alert(
        "Update available",
        "A new version has been downloaded. Restart now to apply it?",
        [
          { text: "Later", style: "cancel" },
          { text: "Restart", onPress: () => Updates.reloadAsync() },
        ]
      );
    }
  } catch (error) {
    // Network errors are expected occasionally, fail silently
    console.log("OTA update check failed", error);
  }
}

6. Staged Rollouts: prozentuale Verteilung und Monitoring

Ein Update sofort an hundert Prozent der Nutzer auszurollen ist riskant, egal wie gründlich intern getestet wurde. EAS Update unterstützt deshalb gestufte Rollouts über eine Rollout-Prozentangabe: Ein neues Update wird zunächst nur an einen kleinen Teil der Installationen ausgeliefert, während der Rest weiterhin die vorherige, bekannt stabile Version erhält. Erst wenn Fehlerraten und Absturzstatistiken für diese erste Kohorte unauffällig bleiben, wird der Prozentsatz schrittweise erhöht, bis am Ende alle Nutzer auf dem neuen Stand sind.

In der Praxis kombiniert man einen Staged Rollout mit Crash-Reporting-Tools wie Sentry oder Bugsnag: Nach der Veröffentlichung an zehn Prozent der Nutzer wird für einige Stunden beobachtet, ob die Crash-freie Rate stabil bleibt und keine neuen Fehlermuster auftauchen. Bleibt alles ruhig, folgt die Erhöhung auf fünfzig Prozent und danach auf hundert Prozent. Dieser Prozess lässt sich vollständig über die EAS Update CLI oder das Dashboard steuern, ohne dass ein neuer nativer Build oder ein erneuter Store-Review nötig wäre.

Gerade für React Native-Teams mit großer Nutzerbasis ist das ein entscheidender Sicherheitsmechanismus: Ein fehlerhaftes OTA-Update trifft im schlimmsten Fall nur die erste, kleine Kohorte, bevor jemand eingreifen kann, statt sofort die komplette Nutzerschaft zu betreffen. Das reduziert das Risiko eines OTA-Rollouts fast auf das Niveau eines normalen, serverseitigen Feature-Flags.

7. Rollbacks: schnell zu einer stabilen Version zurückkehren

Zeigt die Beobachtung während eines Rollouts erhöhte Crash-Raten oder neue Fehler, muss ein Rollback so schnell wie möglich möglich sein, idealerweise ohne dass der Nutzer davon überhaupt etwas mitbekommt. Da jedes über EAS Update veröffentlichte Update eine eindeutige Group-ID trägt, lässt sich der vorherige, als stabil bekannte Stand jederzeit erneut auf denselben Channel veröffentlichen. Dieses Republishing überschreibt effektiv den fehlerhaften Stand, ohne dass irgendetwas neu gebaut werden müsste, das Bundle existiert bereits und muss nur erneut als aktuellste Version für den Channel markiert werden.

Der entscheidende Vorteil gegenüber einem klassischen Store-Rollback: Ein fehlerhaftes natives Binary lässt sich im App Store praktisch nicht zurückziehen, ein neuer Review-Zyklus wäre auch für die Korrektur nötig. Ein fehlerhaftes OTA-Update über EAS Update dagegen lässt sich innerhalb von Minuten korrigieren, weil die gesamte Update-Logik auf Channel- und Branch-Ebene läuft und keine neue native Kompilierung erfordert. In Kombination mit einem vorherigen Staged Rollout bleibt der Schaden eines fehlerhaften Updates ohnehin auf eine kleine Nutzergruppe begrenzt, bevor der Rollback überhaupt greifen muss.


#!/usr/bin/env bash
# Publish a hotfix to only 10% of installs first
eas update --channel production --message "Staged rollout: payment fix" \
  --rollout-percentage 10

# Watch crash-free rate and error counts in Sentry / EAS dashboard before continuing

# Widen the rollout once the first cohort looks healthy
eas channel:edit production --rollout-percentage 50

# Complete the rollout to 100% of installs
eas channel:edit production --rollout-percentage 100

# Roll back instantly: republish the previous known-good update group
eas update:republish --group PREVIOUS_GOOD_UPDATE_GROUP_ID --channel production

8. Grenzen von OTA: was EAS Update nicht aktualisieren kann

So mächtig EAS Update ist, es hat eine klare, bewusste Grenze: Alles, was nativen Code betrifft, kann niemals über OTA ausgeliefert werden. Wird ein neues natives Modul integriert, etwa eine neue Kamera-Bibliothek, ein neues Bluetooth-SDK oder eine geänderte native Berechtigung in Info.plist beziehungsweise AndroidManifest.xml, reicht ein reines JS-Update nicht mehr aus. In diesem Fall ist ein neuer EAS Build zwingend erforderlich, gefolgt von einer regulären Einreichung im App Store und Play Store samt vollständigem Review-Zyklus.

Auch App-Icons, Splash-Screens auf nativer Ebene, native Berechtigungsanfragen und alles, was Änderungen an der kompilierten Binärdatei selbst erfordert, fällt außerhalb des OTA-Umfangs. Genau dafür existiert die Runtime-Version-Prüfung aus Abschnitt zwei: Sie stellt sicher, dass ein Nutzer mit altem Binary niemals ein JS-Update erhält, das auf ein nicht vorhandenes natives Modul zugreifen würde. Statt eines Absturzes bleibt die App einfach auf der letzten kompatiblen Version, bis der Nutzer über den Store aktualisiert.

Für Teams bedeutet das in der Praxis eine klare Faustregel: Reine JavaScript-Änderungen, Business-Logik, Styling, Texte, API-Aufrufe und Bugfixes innerhalb bestehender nativer Grenzen gehören zu EAS Update. Neue native Abhängigkeiten, geänderte native Berechtigungen und alles, was ein neues natives SDK voraussetzt, gehört zwingend in einen neuen EAS Build mit anschließendem Store-Review. Diese Grenze zu respektieren ist auch der Grund, warum Apple OTA-Updates in React-Native-Apps überhaupt toleriert, siehe Abschnitt neun.

9. EAS Update im Vergleich: CodePush, App-Store-only und App-Store-Richtlinien

Microsoft hat sein App Center und damit auch CodePush im Frühjahr 2025 endgültig eingestellt. Für Teams, die jahrelang auf CodePush als OTA-Lösung gesetzt hatten, war das ein erzwungener Wechsel, kein optionales Upgrade. EAS Update ist dabei kein zufälliger Ersatz, sondern der naheliegende Nachfolger: Es stammt vom selben Anbieter wie Expo und EAS Build, ist tief in den Expo-Workflow integriert und bietet mit Channels, Branches und Runtime-Version-Prüfung ein deutlich robusteres Modell als das einfachere Deployment-Konzept von CodePush.

Wichtig für jedes OTA-Setup ist auch die Frage, was Apple überhaupt erlaubt. Nach Apples App-Store-Review-Richtlinien darf interpretierter Code, wie er über EAS Update ausgeliefert wird, den primären Zweck der App nicht verändern und keine Funktionen nachladen, die inhaltlich über das hinausgehen, was beim ursprünglichen Review geprüft wurde. Bugfixes, Textänderungen, Layout-Anpassungen und Business-Logik innerhalb des bestehenden Funktionsumfangs sind ausdrücklich zulässig, komplett neue Features, die den Charakter der App verändern, oder das Nachladen von Funktionalität, die die im Review geprüften Rechte umgeht, sind es nicht. EAS Update respektiert diese Grenze technisch bereits durch die Runtime-Version-Kopplung an native Builds.

Kriterium CodePush (eingestellt) EAS Update Nur App-Store-Release
Review-Zeit für Bugfixes Keiner (OTA) Keiner (OTA) Stunden bis Tage pro Store
Rollback-Geschwindigkeit Minuten (Server abgeschaltet) Minuten, per Republish Neuer Review-Zyklus nötig
Native-Code-Unterstützung Nein, nur JS/Assets Nein, nur JS/Assets Ja, voller nativer Code
Hosting / Betrieb Eingestellt seit 2025 Von Expo/EAS gehostet, aktiv gepflegt Kein separates Hosting nötig
Runtime-Kompatibilitätsprüfung Manuell, fehleranfällig Eingebaut über Runtime Version Entfällt (immer volles Binary)

Der Vergleich macht deutlich, warum EAS Update aktuell die naheliegendste Wahl für OTA-Updates in React-Native- und Expo-Apps ist: CodePush existiert schlicht nicht mehr als aktiv gewartete Option, reine App-Store-Releases sind für kleine Fixes zu langsam, und EAS Update deckt genau die Lücke dazwischen ab, ohne Apples Regeln zu verletzen.

Mironsoft

React Native, Expo und mobile Deployment-Pipelines

OTA-Updates für eure React-Native-App sauber aufsetzen?

Wir richten EAS Update mit Channels, Branches und Runtime-Version-Policy ein, bauen gestufte Rollouts mit Monitoring auf und sorgen dafür, dass Rollbacks im Ernstfall in Minuten statt Tagen greifen.

EAS Update Setup

Channels, Branches und Runtime-Version-Policy passend zu eurer Release-Strategie konfigurieren

Staged Rollouts

Prozentuale Rollout-Strategien mit Crash-Monitoring und klaren Eskalationsstufen aufbauen

CodePush-Migration

Bestehende CodePush-Integrationen sauber auf EAS Update umziehen

10. Zusammenfassung

EAS Update liefert JavaScript-Bundle- und Asset-Updates direkt an installierte React-Native- und Expo-Apps aus, ganz ohne neuen App-Store- oder Play-Store-Review. Das Channel-zu-Branch-Mapping erlaubt es, den Update-Fluss jederzeit umzulenken, während die Runtime-Version-Prüfung zuverlässig verhindert, dass ein altes Binary ein inkompatibles OTA-Update erhält und abstürzt. Über die eas update CLI und eas.json lassen sich Veröffentlichungen, gestufte Rollouts und Rollbacks vollständig ohne neuen nativen Build steuern.

Klar bleibt die Grenze: Alles, was native Module, native Berechtigungen oder Änderungen an der kompilierten Binärdatei betrifft, braucht weiterhin einen neuen EAS Build und einen regulären Store-Review, das ist auch der Rahmen, den Apples Richtlinien für OTA-Content vorgeben. Mit dem Ende von CodePush im Jahr 2025 ist EAS Update für React-Native- und Expo-Teams der konsequente, aktiv gepflegte Nachfolger für schnelle, sichere OTA-Updates.

EAS Update für React Native, OTA-Updates auf einen Blick

Was OTA kann

JS-Bundle und Assets direkt an installierte Apps ausliefern, ohne App-Store- oder Play-Store-Review, innerhalb von Minuten statt Tagen.

Channels, Branches, Runtime Versions

Channel routet zur Laufzeit auf einen Branch, Runtime Version verhindert inkompatible Updates auf alten nativen Binaries.

Staged Rollout & Rollback

Rollout-Prozentsätze schrittweise erhöhen, Crash-Raten beobachten, fehlerhafte Updates per Republish in Minuten zurückrollen.

Grenzen von OTA

Neue native Module, geänderte native Berechtigungen und Binary-Änderungen brauchen zwingend einen neuen EAS Build plus Store-Review.

11. FAQ: EAS Update und OTA-Updates in React Native

1Was ist EAS Update genau?
Der OTA-Update-Dienst von Expo: liefert neue JS-Bundles und Assets direkt an installierte React-Native-Apps aus, ohne neuen Store-Review.
2Channel vs. Branch?
Branch ist der Update-Strang, auf den veröffentlicht wird. Channel ist fest in die App einkompiliert und bestimmt, welchen Branch sie zur Laufzeit abfragt.
3Was ist eine Runtime Version?
Beschreibt die native API-Oberfläche eines Builds. Updates werden nur bei exakter Übereinstimmung ausgeliefert, das verhindert Abstürze durch fehlende native Module.
4Native Module per EAS Update hinzufügen?
Nein, dafür ist immer ein neuer EAS Build und ein regulärer Store-Review nötig. EAS Update aktualisiert nur JavaScript und Assets.
5Wie schnell kommt ein Update an?
Sofort verfügbar nach Veröffentlichung, üblicherweise beim nächsten oder übernächsten App-Start automatisch geprüft und angewendet.
6Wann Staged Rollout nutzen?
Bei jedem risikobehafteten Update, besonders bei kritischer Business-Logik wie Checkout, um den Effekt eines Fehlers auf eine kleine Kohorte zu begrenzen.
7Wie funktioniert ein Rollback?
Die vorherige Update-Group wird per eas update:republish erneut auf denselben Channel veröffentlicht, ohne neuen nativen Build, meist in wenigen Minuten.
8Ist CodePush wirklich tot?
Ja, Microsoft hat App Center inklusive CodePush 2025 eingestellt. EAS Update ist der aktiv gepflegte, technisch robustere Nachfolger.
9Erlaubt Apple OTA-Updates?
Ja, solange der primäre Zweck der App unverändert bleibt und keine über den Review hinausgehenden Funktionen nachgeladen werden.
10Neuer Review pro OTA-Update nötig?
Nein, das ist der Kernvorteil. Ohne native Änderungen läuft die Auslieferung komplett ohne neuen App-Store- oder Play-Store-Review.