Umgang mit Native-Foldern als Build-Ausgabe mithilfe von Expo Prebuild und CNG
Wie Continuous Native Generation es einer Expo-App ermöglicht, benutzerdefinierte native Module, Konfigurations-Plugins sowie EAS-Secrets zu verwenden, ohne die ios- und android-Verzeichnisse bearbeiten oder kommitten zu müssen.
Jahrelang standen die React Native-Teams bei Expo vor derselben Entscheidung: Sobald ein Projekt eine benutzerdefinierte native Modul, Hintergrundmusik oder ein SDK eines Anbieters benötigte, war die Lösung expo eject, wodurch das saubere JavaScript-Projekt plötzlich über vollständige ios- und android-Verzeichnisse verfügte. Von da an musste das Team auch CocoaPods pflegen, build.gradle bearbeiten und Xcode-Fehler beheben. Continuous Native Generation (CNG) sowie Expo Prebuild beseitigen diesen Kompromiss. Diese Anleitung erläutert, wie das Modell funktioniert, wie Konfigurations-Plugins manuelle Anpassungen im Native-Bereich ersetzen, wie man von kaputten lokalen Android-Kompilierungen wiederherstellt und wie Geheimnisse in Cloud-Kompilierungen eingegeben werden können, ohne sie zu speichern.
Nativer Code als Build-Artifact
CNG basiert auf einem Prinzip: Die nativen Projekte werden generiert, anstatt manuell gepflegt zu werden.
Durch Ausführung von npx expo prebuild entstehen die ios- und android-Ordner aus einer einzigen Quelle, nämlich Ihrer Datei app.json oder app.config.js. Prebuild liest diese Konfiguration, wendet die darin beschriebenen Anpassungen für die native Umgebung an und erzeugt vollständige, kompilierbare Projekte für diese Plattformen.
Weil diese Ordner jederzeit neu erstellt werden können, fügen viele Teams die Verzeichnisse /ios und /android zu .gitignore hinzu. Wenn eine native Abhängigkeit in einem fehlerhaften Zustand ist oder Sie React Native aktualisieren, werfen Sie die Ordner weg und erstellen sie erneut. Die tägliche Frage ändert sich von „Was hat jemand am Xcode-Projekt geändert?“ zu „Was besagt die Konfiguration?“.
Das legt auch die einzige Regel des Modells fest: Sobald native Ordner erstellt wurden, sollten sie nicht manuell bearbeitet werden. Jede manuelle Änderung verschwindet bei der nächsten Vorbereitungsphase. Falls eine Änderung notwendig ist, muss sie über die Konfiguration vorgenommen werden.
Konfigurations-Plugins ersetzen manuelle Bearbeitungen von Native-Dateien
Das wirft eine offensichtliche Frage auf: Wie fügt man Berechtigungen in die AndroidManifest.xml ein oder passt AppDelegate.mm an, wenn die generierten Dateien nicht bearbeitet werden dürfen?
Konfigurations-Plugins sind die Lösung. Ein Konfigurations-Plugin ist eine JavaScript-Funktion, die während der Vorbereitungsphase ausgeführt wird und das Native-Projekt auf kontrollierte, wiederholbare Weise modifiziert. Apps mit anspruchsvollen Anforderungen an die Native-Implementierung, wie z. B. Echtzeit-Sprachverarbeitung oder die Darstellung von 3D-Modellen, sind auf Bibliotheken angewiesen, die tiefgreifende Anbindungen an das Betriebssystem benötigen – und solche Bibliotheken liefern in der Regel ihre eigenen Plugins mit.
Anstelle der Bearbeitung des nativen Codes listen Sie das Plugin sowie seine Optionen in app.json auf. Das untenstehende Beispiel verwendet expo-build-properties, um die Android-Variable compileSdkVersion auf 34 zu setzen – ein Wert, der sonst in einer Gradle-Datei enthalten wäre:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"compileSdkVersion": 34
}
}
]
]
}
}
Beim nächsten Vorbau schreibt das Plugin diese Einstellung in das generierte Android-Projekt. Da die Änderung deklariert und nicht manuell angewendet wird, bleibt sie bei jeder Neugenerierung erhalten und ist in Code-Reviews sichtbar.
Aufrechterhaltung einer intakten lokalen Android-Kompilierung
Expo Go eignet sich hervorragend für das frühe Prototyping, enthält aber nur die mitgelieferten nativen Module. Sobald man auf benutzerdefinierten Native-Code angewiesen ist, werden Tests mit Entwicklungsversionen durchgeführt, indem man npx expo run:android oder npx expo run:ios verwendet. Das ist besonders wichtig für Apps, die viel Rechenleistung vor Ort benötigen, wie beispielsweise solche mit KI-Funktionen, bei denen man eine echte Leistung auf einem Gerät oder Emulator sehen muss.
Die Android-Entwicklungsumgebung hat den Ruf, empfindliche Caches zu haben. Ein typisches Szenario: Man fügt eine Abhängigkeit hinzu, und der nächste lokale Build scheitert an einem unklaren Java- oder Gradle-Fehler. Die Ursache liegt in der Regel in veralteten Build-Ausgaben und nicht im eigenen Code.
Ein sauberer Build ist das Erste, was man ausprobieren sollte. Gehen Sie in den erzeugten android-Ordner, führen Sie Gradles „clean“-Aufgabe aus, um die gespeicherten Ausgaben zu löschen, kehren Sie anschließend zum Projektverzeichnis zurück und bauen Sie erneut auf:
cd android
./gradlew clean
cd ..
npx expo run:android
Falls allein das Reinigen nicht hilft, bietet CNG eine effektivere Lösung: npx expo prebuild --clean löscht die nativen Verzeichnisse vollständig und erstellt sie neu – was sicher ist, weil sich darin nichts manuell verwalten lässt. Wenn man diese Vorgehensweisen in seine Routine integriert, entfallen lange Debugging-Sitzungen.
Übermittlung von Geheimnissen für EAS-Cloud-Builds
CNG ist besonders nützlich in Kombination mit EAS (Expo Application Services) für Cloud-Builds.
Nehmen wir die Fehlerüberwachung: Produktivanwendungen benötigen sie, und die Integration von Sentry erfordert das Hochladen von Source Maps – wofür ein SENTRY_AUTH_TOKEN benötigt wird. Früher musste dieser Token in jedes Build-Umfeld gelangen, ohne im Repository zu landen, was die Verwaltung erschwerte.
Mit CNG und EAS fügen Sie Sentrys Konfigurations-Plugin zu app.json hinzu und speichern den Token niemals ab. Stattdessen registrieren Sie ihn über die CLI als Umgebungsvariable in EAS, wodurch er nur im „secret“-Modus und im Projektbereich sichtbar ist – somit steht er den Builds zur Verfügung, wird danach aber nicht angezeigt. Führen Sie den Befehl einmal aus und ersetzen Sie dabei den Platzhalterwert durch Ihren tatsächlichen Token:
eas env:create --name SENTRY_AUTH_TOKEN --value your_token_here --visibility secret --scope projecteas env:create --name SENTRY_AUTH_TOKEN --value your_token_here --visibility secret --scope project
Während eines Cloud-Builds führt EAS den Prebuild-Abschnitt aus, um die nativen Projekte zu generieren. Das Sentry-Plugin liest den geheimen Wert aus der Umgebung ab, konfiguriert das native SDK und lädt die Quellkarten hoch. Weder Dateien im nativen Format noch der Token gelangen jemals in den Versionskontrollsystem. Die genauen Flags von eas env:create können zwischen den CLI-Versionen variieren; prüfen Sie daher die aktuelle EAS-Dokumentation, falls der Befehl abgelehnt wird.
Wann CNG besondere Vorsicht erfordert
Das Modell ist leistungsstark, doch in einigen Situationen ist Planung erforderlich:
- Bibliotheken ohne Plugins. Wenn eine native SDK keine Konfigurations-Plugin bietet, müssen Sie möglicherweise selbst ein kleines lokales Plugin schreiben, anstatt die generierten Dateien zu bearbeiten.
- Bestehende Brownfield-Projekte. Apps mit jahrelang manuell bearbeitetem Native-Code können ihre Ordner nicht einfach löschen; die Migration bedeutet, jede Anpassung zunächst in die Konfiguration zu übertragen.
- Teamdisziplin. CNG funktioniert nur, wenn alle
iosundandroidals verwerflich betrachten. Eine einzige schnelle Bearbeitung in Xcode geht bei der nächsten Regeneration stillschweigend verloren.
Zusammenfassung
Expo Prebuild und CNG machen komplexe, produktionsreife React Native-Apps durch die Verwerflichmachung der nativen Schichten deutlich zugänglicher:
- Deklarieren Sie die nativen Anforderungen in
app.jsonoderapp.config.jsund lassen Sie Prebuild den Rest erzeugen.
prebuild --clean, wenn lokale Builds rätselhaft fehlschlagen.SENTRY_AUTH_TOKEN in den EAS-Umgebungsvariablen, niemals im Repository.Durch die Reduzierung der nativen Projekte auf Build-Ausgaben kann sich das Team wieder auf den React Native-Code, flüssige Benutzeroberflächen und Produktfunktionen konzentrieren.
Verwandte Artikel
- Ein In-App Turbo Module von Anfang bis Ende mit React Native Codegen verbinden — Definieren Sie eine typisierte Spezifikation, führen Sie Codegen aus und implementieren Sie ein Turbo Module für iOS und Android mit synchronen, Promise-, Callback- sowie Event-Emitter-Methoden.
- Persistierter Themenwechsel in React Native mit Context und Hooks — Erstellen Sie einen Themenwechsler für React Native mithilfe von Context, useState und useEffect: Tab-Navigation, ein Themenauswahler, Persistenz mit AsyncStorage sowie ein Ladeindikator beim Starten.