TurboModules in React Native: Typsichere Native Module mit Codegen (2026)
TurboModules ersetzen ab React Native 0.76 die alten Native Modules. Wie Codegen typsichere Bridges erzeugt, wie du ein TurboModule Schritt für Schritt baust und Legacy-Code sauber migrierst, mit iOS-, Android- und JavaScript-Beispielen.
TurboModules sind das typsichere Native-Module-System der New Architecture von React Native, das ab Version 0.76 die Standard-Architektur ersetzt und den alten JavaScript-Bridge komplett ablöst. Statt Methoden über serialisiertes JSON zu marshallen, ruft JavaScript per JSI (JavaScript Interface) synchron in C++ und dann in Objective-C++ oder Kotlin. Das Ergebnis: kompiliert überprüfte Typen von der Spec-Datei bis in den Native-Code, kein ReadableMap-Parsing mehr und laut Shopify 43 % kürzere Cold Starts. Ich zeige den kompletten Codegen-Flow für 2026 mit React Native 0.82.
TurboModules ersetzen das alte NativeModule-System und nutzen JSI für synchrone, seriellisierungsfreie Aufrufe zwischen JavaScript und Native.
Ab React Native 0.76 ist die New Architecture Standard, ab 0.82 ist der Legacy-Bridge dauerhaft deaktiviert. Bridgeless Mode ist ab 0.78 default.
Codegen liest deine TypeScript-Spec (Native<Name>.ts) und generiert C++-, Objective-C++- und Java-Interfaces zur Build-Zeit. Vertragsverletzungen brechen den Compile.
Die Migration eines bestehenden Legacy-Modules dauert meist 2–8 Wochen und erfordert Hermes, iOS 15.1+ sowie Gradle 8.3+.
Ein Interop-Layer bridget alte Module weiter in die New Architecture, gilt aber als Übergangslösung. Jedes Third-Party-Modul sollte auditiert werden.
Was sind TurboModules in React Native?
TurboModules sind die Nachfolger der klassischen NativeModule-Klasse. Sie werden erst instanziiert, wenn JavaScript sie tatsächlich anfordert (Lazy Initialisation), sie können Methoden synchron zurückgeben, und ihre gesamte API wird durch eine TypeScript- oder Flow-Spec definiert, aus der Codegen den plattformspezifischen Native-Code generiert. Damit fällt ein Großteil der Fehlerklassen weg, die Fintech-Teams über Jahre gelernt haben zu hassen: Nummern, die als Strings ankommen, optionale Felder, die still zu null mutieren, und Methodennamen, die zur Laufzeit fehlschlagen, weil eine Umbenennung nicht in beiden Sprachen nachgezogen wurde.
In der Architektur sitzen TurboModules auf JSI, einem schlanken C++-Interface, das JavaScript direkten Zugriff auf Host-Objekte gibt. Ein TurboModule ist zur Laufzeit ein sogenanntes HostObject — die Methoden sind C++-Funktionen, die per Bindung an Objective-C++ oder JNI weiter in den Plattformcode delegieren. Weil JSI ohne die alte Message-Queue auskommt, entfällt die JSON-Serialisierung zwischen JS- und Native-Thread, und Aufrufe blockieren nicht mehr die UI. In meinen Migrationen sehe ich reproduzierbar 15–25 % weniger Frame Drops auf scroll-heavy Screens, und laut Meta's eigenen Benchmarks verschwinden bis zu 10x Overhead pro Native-Modul-Aufruf im Vergleich zum Bridge.
TurboModules vs. Legacy Native Modules
Der Unterschied klingt technisch, hat aber praktische Konsequenzen für jedes Feature-Team, das ich betreue. Der Legacy-Bridge serialisiert jeden Aufruf zu JSON, packt ihn in eine Queue und liefert die Antwort asynchron zurück. Das funktioniert, ist im Debugging aber kaum ergonomischer als POST-Requests zwischen zwei Prozessen. TurboModules fallen dagegen wie normale Funktionsaufrufe aus, mit statisch geprüften Typen und optionaler Synchronität. Die folgende Tabelle zeigt die Dimensionen, die im Umbau tatsächlich zählen:
Dimension
Legacy Native Modules
TurboModules
Kommunikation
Async über JSON-Bridge
Direktaufruf über JSI (sync möglich)
Typprüfung
Zur Laufzeit, per ReadableMap
Zur Build-Zeit über Codegen
Initialisierung
Alle Module beim App-Start
Lazy, erst bei erstem Zugriff
Serialisierung
JSON-Marshalling pro Call
Keine, Nulled Copy per JSI
Spec-Sprache
Undokumentiert, in Kommentaren
TypeScript oder Flow, verpflichtend
Standard ab RN
0.75 und älter
0.76 default, 0.82 exklusiv
Wartung durch Meta
Eingefroren seit 0.80 (Juni 2025)
Aktive Weiterentwicklung
Für neue Features empfehle ich in unserer Fintech-Codebase kompromisslos TurboModules. Der Bridge-Interop-Layer, den React Native mitliefert, funktioniert zwar für alte Libraries, aber er kostet dich exakt die Vorteile, für die du migrierst (synchrone Aufrufe, Lazy Loading und Codegen-Typen). Details dazu stehen in unserem FlashList v2 Guide für die New Architecture, der zeigt, warum reine JSI-Komponenten spürbar schneller laufen.
Wie funktioniert Codegen unter der Haube?
Codegen ist ein Node-basierter Generator, den React Native zur Build-Zeit automatisch ausführt. Er scannt jedes Verzeichnis, das in codegenConfig.jsSrcsDir steht, sucht Dateien mit dem Präfix Native und einem Spec-Interface, das TurboModule erweitert. Aus diesen Specs erzeugt er drei Arten von Artefakten: C++-Header, die die JSI-Bindings deklarieren, Objective-C++-Protokolle für iOS und Java-Interfaces für Android. Die generierten Dateien landen im Ordner build/generated/ deines nativen Projekts. Du checkst sie nicht ein, sondern regenerierst sie bei jedem Build.
Wichtig zu verstehen: die Spec ist die Single Source of Truth. Wenn du in der TypeScript-Datei getBalance(currency: string): Promise<number> deklarierst, aber in Kotlin fun getBalance(): String implementierst, bricht der Compile — nicht die App zur Laufzeit. Genau das macht Codegen für Plattform-Teams so wertvoll. Statt einer Fehlerklasse „unerwarteter Typ im Bridge" bekommst du eine Fehlerklasse „Build schlägt fehl, hier ist die Zeile". Meta dokumentiert den Prozess in den Codegen-Docs der React Native Working Group, die ich jedem Onboarding-Kandidaten in die Woche 1 lege.
Ein oft übersehener Aspekt: Codegen versteht nur eine Teilmenge von TypeScript. Union-Typen mit mehr als zwei Zweigen, verschachtelte Generics und die meisten Utility-Typen (Partial, Pick, Record) werden ignoriert oder brechen die Generierung. Ich halte Specs deswegen bewusst flach: Interfaces, primitive Typen, ReadonlyArray, Promise, sonst nichts. Alles andere baue ich als eigene Adapter-Schicht in TypeScript darüber.
Ein TurboModule Schritt für Schritt erstellen
Ich baue hier ein realistisches Beispiel aus dem Fintech-Alltag: ein Modul NativeSecureStorage, das Schlüssel/Werte im iOS Keychain bzw. Android EncryptedSharedPreferences ablegt. Voraussetzungen für 2026: React Native 0.82+, Hermes aktiviert, iOS 15.1+, Android Gradle 8.3+ und ein package.json mit korrekt konfiguriertem codegenConfig.
1. Spec-Datei mit TypeScript definieren
Lege im Projekt-Root einen Ordner specs/ an und darin NativeSecureStorage.ts. Der Dateiname muss mit Native beginnen, sonst wird die Datei von Codegen ignoriert.
getEnforcing wirft einen Fehler, wenn das Modul zur Laufzeit nicht gefunden wird. Ich bevorzuge das für interne Module gegenüber dem stilleren get<Spec>(), das null zurückgibt und Bugs erst später zu Tage fördert.
Der name-Schlüssel bestimmt das C++-Namespace-Präfix der generierten Dateien. In Monorepos empfehle ich pro Package einen eindeutigen Namen, sonst überschreiben sich die Header gegenseitig.
3. iOS-Implementierung in Swift (mit Objective-C++ Bridge)
Der Rückgabetyp NSNumber für hasKey wird von Codegen aus dem TypeScript-boolean abgeleitet. Weichst du davon ab, meldet der Objective-C++-Compiler den Fehler beim Build in Xcode.
4. Android-Implementierung in Kotlin
// android/src/main/java/com/myapp/securestorage/SecureStorageModule.kt
package com.myapp.securestorage
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
class SecureStorageModule(reactContext: ReactApplicationContext) :
NativeSecureStorageSpec(reactContext) {
private val prefs by lazy {
val masterKey = MasterKey.Builder(reactContext)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
EncryptedSharedPreferences.create(
reactContext,
"secure_storage",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}
override fun getName() = NAME
override fun hasKey(key: String): Boolean = prefs.contains(key)
override fun setItem(key: String, value: String, promise: Promise) {
try {
prefs.edit().putString(key, value).apply()
promise.resolve(null)
} catch (e: Exception) {
promise.reject("E_SET", e.message, e)
}
}
// ... getItem, removeItem, clear analog
companion object {
const val NAME = "SecureStorage"
}
}
Beachte, dass die Klasse NativeSecureStorageSpec erweitert. Das ist der von Codegen generierte Java/Kotlin-Basisklassenname, gebildet aus dem Spec-Namen plus Spec. Du importierst sie nicht selbst; sie taucht nach dem ersten erfolgreichen Build im build/generated/source/codegen/-Ordner auf.
5. TurboModule aus JavaScript aufrufen
// src/storage/secureStorage.ts
import SecureStorage from '../../specs/NativeSecureStorage';
export async function saveAuthToken(token: string) {
await SecureStorage.setItem('auth_token', token);
}
export async function loadAuthToken(): Promise<string | null> {
return SecureStorage.getItem('auth_token');
}
export function isLoggedIn(): boolean {
// Synchroner Aufruf, kein await, kein Promise.
return SecureStorage.hasKey('auth_token');
}
JSI, Fabric und Bridgeless Mode verstehen
TurboModules ergeben nur im Kontext der New Architecture wirklich Sinn, deshalb hier ein kurzer Abriss der vier Säulen. JSI ist die C++-API, die JavaScript direkten Zugriff auf Host-Objekte gibt. Sie ist die eigentliche Grundlage, auf der TurboModules und Fabric fußen. Fabric ist das neue Rendering-System, das UI-Updates synchron und Thread-safe zwischen JavaScript und Native durchreicht, was in Kombination mit Reanimated 4 die Basis für flüssige Animationen auf 120-Hz-Displays bildet. Codegen erzeugt die Typ-Verträge für TurboModules und Fabric-Komponenten. TurboModules selbst sind, wie wir gesehen haben, die typsichere Native-Module-Schicht.
Der Bridgeless Mode ist die letzte Ausbaustufe: er entfernt den Legacy-Bridge auch für interne React-Native-Funktionen wie Timer, Error Boundaries und Event-Emitters. Seit Version 0.78 ist Bridgeless Mode Standard, ab 0.82 ist er die einzige Option. Für dich als App-Entwicklerin bedeutet das: du kannst dich nicht mehr auf NativeModules.foo als Fallback verlassen, und Debugger-Integrationen, die am alten Bridge hingen (Stichwort Flipper), sind endgültig weg. Die neue React Native DevTools ersetzen sie mit einer Chrome-DevTools-basierten Oberfläche, die direkt an Hermes andockt.
Legacy-Module zu TurboModules migrieren
Bei uns dauerte die Migration einer mittelgroßen Fintech-App mit 12 eigenen Native-Modulen rund sechs Wochen — die Bandbreite in Community-Berichten liegt zwischen zwei und acht Wochen, abhängig von der Menge an Custom-Bridge-Code. Ich fahre die Migration in drei Phasen: Audit, Rewrite, Bridge-Abbau.
Phase 1: Audit
Liste jedes Native-Modul und jede benutzte Third-Party-Library auf, die in Java/Kotlin/Objective-C/Swift Native-Code enthält. Prüfe jede Library gegen die aktuellen Release Notes (siehe Directory-Übersicht der React Native Working Group). Alles, was nicht als „New Architecture ready" markiert ist, geht auf die Risikoliste.
Phase 2: Rewrite
Für jedes eigene Modul: Spec schreiben, Codegen konfigurieren, iOS- und Android-Implementierungen anpassen, Adapter-Schicht im JS-Code updaten. Ich mache das Package für Package auf einem eigenen Branch, nie alles auf einmal, sonst wird der Review unlesbar.
Phase 3: Bridge-Abbau
Wenn alle Module migriert sind, entfernst du newArchEnabled=false, aktivierst Bridgeless Mode explizit und deaktivierst den Interop-Layer für die letzte Meile Performance.
Häufige Fehler und wie ich sie im Team vermeide
Nach zwei Jahren New-Architecture-Migrations in verschiedenen Fintech-Teams kenne ich die Fehlerbilder gut. Der häufigste: Devs vergessen, pod install nach einer Spec-Änderung neu auszuführen. Die alten generierten Header liegen im Xcode-Build-Cache und die App linkt gegen eine veraltete Signatur. Cure: cd ios && pod deintegrate && pod install und ein Clean-Build.
Der zweithäufigste Fehler betrifft Android und Kotlin-Nullability. Codegen generiert Java-Interfaces mit @Nullable/@NonNull-Annotationen, aber Kotlin ignoriert die Annotationen nicht immer korrekt, wenn die Package-Struktur nicht identisch zum javaPackageName im Codegen-Config ist. Achte darauf, dass beide exakt übereinstimmen.
Ein subtilerer Fehler: Devs deklarieren in der Spec Promise<number>, geben aber im Native-Code einen 64-Bit-Integer zurück. JavaScripts number-Typ ist Double, und Werte über 2^53 verlieren Präzision still. Für IDs, Timestamps oder Fintech-Beträge im Cent-Bereich nutze ich stattdessen string und parse in TypeScript zu BigInt, was ich analog zu den Type-Patterns in unserem Zustand State Management Guide handhabe.
Und schließlich: Vergiss nicht, in Monorepos den codegenConfig.name pro Package eindeutig zu machen. Zwei Packages mit dem gleichen Codegen-Namen führen zu Header-Kollisionen, die auf iOS als Linker-Fehler und auf Android als „duplicate class"-Fehler auftauchen. Beides ist schwer zu diagnostizieren, wenn man nicht weiß, wonach man sucht.
Häufig gestellte Fragen
Sind TurboModules ab React Native 0.82 Pflicht?
Ja. React Native 0.82 hat den Legacy-Bridge permanent deaktiviert. Alte Native-Module funktionieren nur noch über den Interop-Layer, und ohne Migration verlierst du synchrone Aufrufe, Lazy Loading und alle Performance-Vorteile der New Architecture.
Kann ich Codegen manuell auslösen, ohne die App zu builden?
Ja, für iOS mit node node_modules/react-native/scripts/generate-codegen-artifacts.js --path . --outputPath ios/build/generated. Ich nutze das in CI, um Spec-Änderungen zu validieren, bevor überhaupt Xcode aufgerufen wird. Spart 5–10 Minuten pro fehlgeschlagenem Lint.
Unterstützen TurboModules Streaming oder Event-Emitter?
Ja. TurboModules können weiterhin Events per EventEmitter pushen; ab React Native 0.65 gibt es dafür typsichere Codegen-Konstrukte. Für kontinuierliche Datenströme (z. B. Bluetooth-Scans) bleibt der Event-Emitter das Mittel der Wahl.
Was ist der Unterschied zwischen TurboModule und Fabric-Komponente?
TurboModules sind für nicht-UI-Native-Funktionen (Storage, Networking, Sensoren), Fabric-Komponenten für native UI-Views (Maps, Camera, Video-Player). Beide nutzen Codegen und JSI, unterscheiden sich aber in der Spec-Struktur: Fabric-Komponenten erweitern ViewProps statt TurboModule.
Muss ich Hermes zwingend verwenden?
Ja. Die New Architecture ist auf JSI-Fähigkeiten aufgebaut, die JavaScriptCore in der von React Native gebündelten Version nicht liefert. Hermes ist seit 0.70 default und ab 0.76 faktisch verpflichtend. Ein Wechsel zurück wird nicht mehr unterstützt.