EAS Update 2026: Kompletny Przewodnik po Aktualizacjach OTA w React Native (po Wycofaniu CodePush)
Kompletny przewodnik po EAS Update w 2026. Konfiguracja expo-updates, kanały i gałęzie, rollback jednym poleceniem oraz migracja z wycofanego CodePush krok po kroku.
EAS Update to hostowana usługa Expo, która pozwala publikować bezprzewodowe (OTA) aktualizacje JavaScriptu i zasobów statycznych aplikacji React Native, bez przechodzenia przez proces recenzji App Store czy Google Play. Po wycofaniu Microsoft CodePush w marcu 2025 roku, EAS Update stał się de facto standardem dla aktualizacji OTA w ekosystemie React Native w 2026 roku. Konfiguracja zajmuje kilkanaście minut, wymaga biblioteki expo-updates oraz konta Expo, a darmowy plan wystarcza dla większości małych i średnich projektów.
Szczerze mówiąc, sam przechodziłem tę migrację dwa razy (raz na etapie beta, drugi raz po ogłoszeniu ostatecznej daty EOL) i drugie podejście zajęło mi jedno popołudnie zamiast tygodnia. Nie ma tu żadnej magii, jest po prostu solidnie zaprojektowane narzędzie.
EAS Update zastąpił Microsoft CodePush jako główny mechanizm OTA po jego oficjalnym wycofaniu 31 marca 2025 roku.
Aktualizacje OTA obejmują tylko warstwę JavaScript oraz zasoby (obrazy, fonty). Zmiany w kodzie natywnym nadal wymagają nowego buildu i publikacji w sklepie.
Model runtime version i fingerprint chroni przed wypchnięciem niekompatybilnego bundla do starszej wersji aplikacji z innym natywnym kodem.
Kanały (channels) mapują buildy na gałęzie (branches), co pozwala zarządzać środowiskami preview, staging i production z jednej konsoli.
Rollback wykonuje się jednym poleceniem eas update:roll-back-to-embedded, cofając użytkowników do bundla wbudowanego w binarkę ze sklepu.
Darmowy plan Expo obejmuje 1000 miesięcznych aktywnych aktualizacji (MAU), co wystarcza dla projektów w fazie MVP i wczesnego produkcyjnego użytku.
Czym jest EAS Update i dlaczego zastąpił CodePush?
EAS Update to komponent platformy Expo Application Services odpowiedzialny za dostarczanie aktualizacji JavaScript i zasobów statycznych do już zainstalowanych aplikacji React Native. W praktyce oznacza to, że możesz naprawić błąd w logice, zmienić tekst przycisku albo dodać nowy ekran napisany w React, a użytkownicy otrzymają zmianę przy najbliższym uruchomieniu aplikacji, zwykle w kilka sekund.
Do 2025 roku dominującym rozwiązaniem był Microsoft CodePush działający jako część App Center. Microsoft ogłosił wycofanie App Center z dniem 31 marca 2025 roku, co dla tysięcy projektów oznaczało konieczność wyboru następcy. EAS Update wygrał tę migrację z kilku powodów: jest utrzymywany przez zespół Expo (który utrzymuje również sam React Native w wersji managed), integruje się natywnie z expo-updates, wspiera zarówno projekty Expo, jak i „bare” React Native, oraz oferuje wbudowaną obsługę A/B testów przez branch mapping. Alternatywy takie jak self-hostowany Shipit czy własna implementacja oparta o S3 wciąż istnieją, ale dla większości zespołów nakład utrzymania własnej infrastruktury OTA nie ma uzasadnienia biznesowego.
W kontekście architektury Expo, EAS Update współpracuje z nową architekturą React Native 0.80. TurboModules i Fabric nie stanowią przeszkody, o ile fingerprint runtime jest poprawnie zdefiniowany.
Jak działają aktualizacje OTA w React Native?
Mechanizm OTA opiera się na trzech elementach: bundlerze (Metro lub Hermes prekompilator), lokalnym cache klienta oraz serwerze dystrybucji. Kiedy aplikacja startuje, natywna warstwa expo-updates wysyła zapytanie do serwera EAS z metadanymi: identyfikator projektu, aktualny kanał (channel), platforma oraz, co kluczowe, runtime version. Serwer odpowiada manifestem wskazującym najnowszy kompatybilny bundle dla tej kombinacji.
Jeżeli manifest wskazuje nowszą wersję niż ta w cache, biblioteka pobiera bundle w tle i zapisuje go w lokalnym storage. Domyślna polityka ON_LOAD aktywuje nowy bundle dopiero przy następnym uruchomieniu aplikacji, dzięki czemu aktualnie działająca sesja użytkownika nie zostaje przerwana. Alternatywna polityka ON_ERROR_RECOVERY pobiera aktualizacje tylko jeśli poprzednia sesja zakończyła się crashem, co jest bezpieczne dla aplikacji o wysokich wymaganiach niezawodności.
Warto podkreślić, że OTA nie omija natywnej warstwy. Jeżeli dodasz nową bibliotekę z kodem natywnym (np. react-native-mmkv), musisz opublikować nowy build w App Store lub Google Play. EAS Update aktualizuje wyłącznie warstwę JavaScript (bundle Metro/Hermes) oraz assety (PNG, TTF, JSON). To ograniczenie jest funkcją, nie błędem: gwarantuje, że użytkownicy nie otrzymają aktualizacji, która próbuje wywołać nieistniejący moduł natywny.
Instalacja i konfiguracja expo-updates
W projekcie Expo SDK 51+ biblioteka expo-updates jest już wstępnie zainstalowana. W bare React Native (bez managed Expo) musisz ją dodać ręcznie i zarejestrować w kodzie natywnym. Poniższa sekwencja pokrywa oba scenariusze i sprowadza pełną konfigurację do trzech kroków wykonywanych z terminala projektu.
Krok 1: Instalacja pakietów
npm install -g eas-cli
npx expo install expo-updates
eas login
eas init --id <your-project-id>
eas update:configure
Polecenie eas update:configure automatycznie modyfikuje app.json (dodając sekcję updates oraz runtimeVersion) i, w przypadku bare projektów, wstrzykuje potrzebne wpisy do AndroidManifest.xml i Info.plist. Warto zweryfikować wynik ręcznie. Automatyzacja czasami pomija custom flavory Android (u mnie tak było przy projekcie z trzema wariantami build).
Policy fingerprint to najbardziej rekomendowana opcja w 2026 roku. EAS automatycznie hashuje wszystkie natywne zależności i wersje SDK, przez co runtime version zmienia się tylko wtedy, gdy realnie zmienia się warstwa natywna. Alternatywne polityki appVersion i nativeVersion istnieją głównie dla wstecznej kompatybilności ze starszymi projektami.
Krok 3: Weryfikacja instalacji
import * as Updates from 'expo-updates';
import { useEffect } from 'react';
export function useUpdateChecker() {
useEffect(() => {
async function check() {
if (__DEV__) return;
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
}
} catch (error) {
console.warn('EAS Update check failed', error);
}
}
check();
}, []);
}
Ten hook wykonuje ręczne sprawdzenie aktualizacji przy starcie. Przydatne, gdy chcesz wymusić natychmiastowy restart z nowym bundlem zamiast czekać na kolejne uruchomienie. Pamiętaj o wyłączeniu logiki w trybie deweloperskim (__DEV__), bo Metro sam obsługuje hot reload.
Kanały i gałęzie: strategia wydań
Model EAS Update jest oparty na dwóch pojęciach: channel (kanał) i branch (gałąź). Kanał jest właściwością buildu, wpisywany do binarki podczas eas build i niezmienialny po fakcie. Gałąź jest właściwością aktualizacji, czyli łańcuchem publikowanych bundli, między którymi można dowolnie przełączać mapping.
W praktyce oznacza to, że build z kanałem production na starcie odczytuje branch przypisany temu kanałowi (np. również production). Jeżeli chcesz przetestować hotfix na produkcyjnych binarkach, tworzysz nową gałąź hotfix-1, publikujesz tam aktualizację, i po sanity check przemapowujesz production → hotfix-1. Cofnięcie zmiany to jedno polecenie, a nowe wdrożenie nie wymaga rebuildowania binarki.
Aspekt
Channel
Branch
Ustawiany
Podczas build
Podczas publish
Zmienialny
Nie (bez rebuild)
Tak (przez mapping)
Cel
Segmentacja binarek
Grupowanie updateów
Typowe wartości
preview, staging, production
main, hotfix-1, ab-test-A
Rollback
Rebuild i redeploy w store
Remap kanału (natychmiastowe)
Rekomendowana strategia startowa dla większości zespołów: trzy kanały development, preview, production, każdy zmapowany na własną gałąź o tej samej nazwie. Rozszerzone modele (A/B testing przez branch mapping z warunkami runtime, canary releases dla 5% użytkowników) opisuje sekcja o migracji poniżej.
Runtime version i fingerprint: klucz do bezpiecznych aktualizacji
Runtime version to identyfikator warstwy natywnej. Aktualizacja OTA zostanie zaakceptowana przez klienta tylko wtedy, gdy jej runtime version dokładnie pasuje do runtime version binarki. Jest to zabezpieczenie przed sytuacją, w której nowy bundle JavaScript próbuje wywołać moduł natywny nieistniejący w starszej binarce.
W 2026 roku Expo rekomenduje policy: "fingerprint", wprowadzone w SDK 51 i domyślne od SDK 52. Fingerprint to hash SHA-256 wszystkich elementów natywnych: zainstalowanych bibliotek, wersji SDK, patchy w node_modules/.patches, oraz custom kodu w android/ i ios/ (w projektach bare). Jeżeli dodasz nową bibliotekę z kodem natywnym, fingerprint się zmieni, EAS przydzieli nową runtime version i stare binarki nie otrzymają nowej aktualizacji, dopóki nie opublikujesz nowego buildu w store.
Aby sprawdzić aktualny fingerprint przed publikacją, użyj: npx expo-updates fingerprint:generate. Wynik można zapisać w CI i porównać w PR review. Każda zmiana fingerprint oznacza, że PR wymaga nowego buildu w store, nie tylko OTA. To zdyscyplinowane podejście oszczędza godziny debugowania „dlaczego moja aktualizacja nie dochodzi do użytkowników”.
Publikowanie aktualizacji z EAS CLI
Podstawowe polecenie publikacji jest jednolinijkowe:
eas update --branch production --message "Fix: crash on empty cart"
EAS CLI buduje bundle Metro dla iOS i Android (domyślnie oba na raz), oblicza fingerprint, uploaduje bundle i assety na CDN, i tworzy nowy update w wybranej gałęzi. Cały proces trwa zwykle 30–90 sekund dla przeciętnego projektu. U mnie ostatnio zajął dokładnie 47 sekund, więc te liczby są realistyczne.
Praktyczne flagi, które warto znać:
--platform ios, publikacja tylko dla jednej platformy (przydatne przy hotfixach specyficznych dla iOS)
--auto, automatycznie ustawia branch na bieżący branch git i message na ostatni commit
--republish, kopiuje istniejący update do innej gałęzi bez rebuildu bundla (przydatne przy promocji z staging do production)
--json, output w formacie JSON dla skryptów CI
--non-interactive, wymagane w środowiskach CI, w których nie ma dostępu do TTY
Weryfikacja aktualizacji przed masowym rolloutem: opublikuj do gałęzi preview, zainstaluj aplikację preview na kilku urządzeniach zespołu, i dopiero po sanity check zremapuj kanał production. Analogiczną strategię testowania natywnych zmian omawia nasz przewodnik po React Native DevTools 2026, który uzupełnia debugowanie o narzędzia po wycofaniu Flippera.
Automatyzacja z GitHub Actions
Ręczna publikacja z lokalnego CLI działa dla małych zespołów, ale w projektach produkcyjnych warto zautomatyzować pipeline. Poniżej minimalna konfiguracja GitHub Actions, która publikuje OTA update po merge do main:
name: EAS Update
on:
push:
branches: [main]
jobs:
update:
name: Publish OTA update
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
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- name: Publish update
run: eas update --branch production --message "${{ github.event.head_commit.message }}" --non-interactive
Sekret EXPO_TOKEN generujesz w konsoli Expo (Access Tokens → Create). Warto ograniczyć jego uprawnienia do konkretnego projektu i zakresu update, aby minimalizować ryzyko w razie wycieku.
Dla zaawansowanych pipeline'ów (multi-environment, PR preview updates) rozważ użycie oficjalnej akcji expo/expo-github-action, która wspiera również komentowanie PR z linkiem do preview updateu skanowanym QR kodem. Ten sam wzorzec integracji sprawdza się dla projektów wykorzystujących Expo Router do nawigacji opartej na plikach, gdzie każdy nowy ekran automatycznie ląduje w kolejnym updateu.
Rollback: jak bezpiecznie wycofać złą aktualizację
Nawet z najlepszym QA prędzej czy później opublikujesz aktualizację, która crashuje aplikację lub psuje kluczowy przepływ. EAS Update oferuje dwa mechanizmy odzyskiwania: przemapowanie kanału na poprzednią gałąź oraz roll-back-to-embedded.
Pierwszy scenariusz. Wróć do poprzedniej aktualizacji:
eas channel:edit production --branch previous-stable
To polecenie zmienia mapping tak, że kolejne żądania klientów z kanału production otrzymują ostatnią aktualizację z gałęzi previous-stable zamiast production. Zmiana propaguje się w ciągu sekund. Wadą jest to, że działa tylko jeśli poprzednia gałąź istnieje i zawiera kompatybilną runtime version.
Drugi scenariusz. Wróć do bundla wbudowanego w binarkę (embedded update):
eas update:roll-back-to-embedded --branch production
To polecenie publikuje specjalny „rollback marker” w gałęzi. Klienci odczytujący ten marker ignorują wszystkie OTA updates i uruchamiają bundle który został wgrany podczas eas build. Jest to najsilniejszy fallback, zawsze działa, o ile embedded bundle jest sensowny. Pamiętaj, że użytkownicy stracą dostęp do wszystkich funkcji wprowadzonych OTA po ostatnim build w store, więc traktuj tę opcję jako break-glass.
Migracja z CodePush do EAS Update krok po kroku
Jeżeli twoja aplikacja nadal używa CodePush pomimo oficjalnego wycofania App Center, migracja jest pilna. Endpointy CodePush mogą przestać odpowiadać, a aplikacje utkną na embedded bundlach bez możliwości aktualizacji. Poniżej kompletna sekwencja migracji.
Usuń CodePush z projektu. Wyczyść react-native-code-push z package.json, usuń wpisy CodePush z MainApplication.kt (Android) i AppDelegate.mm (iOS), i usuń wywołania codePush() otaczające root component.
Zainstaluj expo-updates. Nawet w bare React Native możesz użyć npx install-expo-modules aby wstępnie skonfigurować niezbędne moduły natywne.
Uruchom eas update:configure. To polecenie skonfiguruje projekt automatycznie. Zweryfikuj wynik ręcznie, szczególnie w projektach z niestandardowymi Gradle flavors.
Zmapuj kanały CodePush → EAS. Deployment „Staging” w CodePush odpowiada mniej więcej channelowi „preview”, a „Production” idzie na „production”. Zdefiniuj nazwy kanałów w eas.json.
Wykonaj EAS build i dystrybucję. Kluczowe: użytkownicy dostaną OTA tylko po zainstalowaniu nowej binarki z EAS Update wpiętym natywnie. Migracja to zawsze najpierw store release, potem OTA.
Monitoruj adopcję nowej binarki. Użyj EAS Insights lub własnej telemetrii do monitorowania procentu użytkowników na starym CodePush vs nowym EAS. Nie wyłączaj CodePush endpointa, dopóki nie osiągniesz 95%+ migracji.
Dla projektów z aktywnym rozwojem funkcji styling'u polecamy zestawienie w naszym porównaniu NativeWind vs Tamagui vs Unistyles 3, ponieważ zmiany w bibliotekach stylizacji często wymagają bump'a runtime version i osobnego cyklu build+OTA.
Ile kosztuje EAS Update w 2026 roku?
Model cenowy Expo w 2026 opiera się na Monthly Active Updates (MAU), czyli unikalnych instalacjach aplikacji, które odpytały serwer o aktualizację w danym miesiącu. Darmowy plan Free pokrywa 1000 MAU/miesiąc; plan Production zaczyna się od 99 USD/miesiąc za 200 000 MAU, a wyższe wolumeny są wyceniane indywidualnie. Do MAU nie liczy się faktyczna liczba aktualizacji, tylko unikalne instalacje: jeden użytkownik odpytujący serwer 30 razy dziennie liczy się jak 1 MAU. Dla dokładnej aktualnej wyceny sprawdź stronę Expo Pricing, ponieważ progi się okresowo zmieniają.
W porównaniu do samohostowanej infrastruktury OTA (CDN + backend + magazyn + monitoring), EAS Update w wariancie płatnym często wychodzi taniej dla zespołów do ~500 000 MAU. Powyżej tego progu ekonomika może się zmieniać na korzyść własnego rozwiązania, ale wtedy dochodzi koszt zespołu utrzymującego cały pipeline.
Najczęściej zadawane pytania
Czy EAS Update jest darmowy?
Tak, do 1000 Monthly Active Updates (unikalnych aplikacji sprawdzających aktualizacje) w miesiącu. To wystarcza dla MVP i projektów wewnętrznych. Powyżej tego progu obowiązują plany płatne, zaczynające się od 99 USD/miesiąc za 200 000 MAU.
Co zastępuje CodePush po jego wycofaniu?
Głównym zamiennikiem CodePush jest EAS Update od Expo. Alternatywy obejmują self-hostowany expo-updates z własnym backendem oraz komercyjne rozwiązania jak Bitrise Release Management, ale ekosystem React Native w 2026 skonsolidował się wokół EAS Update.
Czy mogę używać EAS Update w bare React Native (bez managed Expo)?
Tak. EAS Update wspiera zarówno projekty managed Expo, jak i bare React Native. W bare projektach musisz dodać moduł expo-updates ręcznie i skonfigurować odpowiednie wpisy natywne w AndroidManifest oraz Info.plist. Polecenie eas update:configure zrobi to w większości przypadków automatycznie.
Ile czasu zajmuje dostarczenie aktualizacji OTA użytkownikowi?
Od momentu publikacji aktualizacji do jej pobrania przez klienta mija zwykle kilka sekund. Aktualizacja aktywuje się jednak dopiero przy następnym uruchomieniu aplikacji (polityka ON_LOAD), więc realny „time to user” zależy od tego, jak często użytkownicy resetują aplikację. Typowo 24–48 h dla 90%+ bazy użytkowników.
Czy OTA aktualizacje naruszają wytyczne App Store i Google Play?
Nie, dopóki aktualizacje nie zmieniają deklarowanej funkcjonalności aplikacji ani nie służą do obchodzenia procesu recenzji. Zarówno Apple (App Store Guidelines 3.3.2) jak i Google Play akceptują aktualizacje warstwy skryptowej w zakresie oryginalnego przeznaczenia aplikacji. EAS Update, aktualizując wyłącznie JavaScript i statyczne zasoby, mieści się w tych granicach.
Porównanie czterech rozwiązań do stylizacji w React Native 2026: StyleSheet API, NativeWind v4, Tamagui i Unistyles 3. Benchmarki, przykłady kodu i wskazówki, którą wybrać.
Flipper został oficjalnie wycofany z domyślnej konfiguracji React Native. W jego miejsce wchodzą nowe React Native DevTools — debugger oparty na Chrome DevTools z natywnym wsparciem dla Hermes. Sprawdź, jak debugować aplikacje React Native w 2026 roku.
Praktyczne porównanie trzech najpopularniejszych bibliotek do zarządzania stanem w React Native w 2026: Zustand, Redux Toolkit i Jotai. Benchmarki, kod produkcyjny, integracja z AsyncStorage oraz wskazówki, którą bibliotekę wybrać dla Twojego projektu mobilnego.