Turbo Modules, React Native New Architecture’ın native API katmanıdır. Tip sözleşmesi compile-time’da tanımlanır, binding JSI (doğrudan çağrı) üzerinden yapılır, init lazy’dir (ilk çağrıda yükleme).
“NativeModules’un yeni adı” değildir — keşif modelinden sözleşme modeline geçiştir. Eski dünyada NativeModules.Camera runtime’da vardı ya da yoktu; Turbo’da Spec yoksa build kırılır veya getEnforcing açıkça throw eder.
Neden Turbo Modules?
Eski Native Module sorunları:
- Runtime keşif → yanlış method adı production sürprizi
- Erken yükleme → kullanılmayan SDK cold start’ı şişirir
- Serileştirme vergisi → her çağrı JSON bridge üzerinden
- Tip güvenliği yok
Turbo Modules şunu getirir:
- Spec (TypeScript/Flow) ile API tek kaynak
- Codegen (kod üreteci) platform iskeleti üretir
- Lazy init → cold start iyileşir
- JSI → serileştirme köprüsü olmadan host object çağrısı
Spec: sözleşme olarak düşünün
Spec sadece TypeScript değil; native ekiplerle paylaşılan API kontratıdır:
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
readonly getConstants?: () => {
sdkVersion: string;
};
add(a: number, b: number): number; // sync
fetchToken(userId: string): Promise<string>; // async
}
export default TurboModuleRegistry.getEnforcing<Spec>('NativeSampleModule');
getEnforcing modül yoksa throw eder — sessiz undefined anti-pattern’ini öldürür. Optional için TurboModuleRegistry.get kullanın.
Codegen yapılandırması
package.json veya app config içinde codegenConfig:
{
"name": "NativeSampleModuleSpec",
"type": "modules",
"jsSrcsDir": "src/specs",
"android": { "javaPackageName": "com.example.sample" }
}
CI tuzakları:
- Spec yolu yanlış → codegen çalışmaz
- New Arch kapalı build → generated sınıflar farklı
- Monorepo’da path kırılır
- Registry string adı ile native module name uyuşmazlığı
Codegen çıktısının CI’da üretildiğini doğrulayın.
Sync vs async
| Metot tipi | Ne zaman | Risk |
|---|---|---|
| Sync | Küçük okuma: flag, path, cache hit | JS thread bloklanır |
| Async (Promise) | Disk, ağ, kamera, permission | Daha güvenli varsayılan |
| Event / callback | Stream, sensor, push | removeListeners unutulursa leak |
Varsayılan async olsun. Sync’i yalnızca ölçülmüş hot path için kullanın. Sync metot içinde disk/network = ANR ve frame drop.
getConstants içine ağır iş koymayın — constants gerçekten sabit olmalı.
Lazy init: kazanç ve ilk çağrı spike’ı
Kullanılmayan modül yüklenmez → cold start iyileşir. Ama ağır SDK (ML, harita, ödeme) ilk dokunuşta spike üretebilir.
Çözüm: Explicit warmup(): Promise<void> async metodu; splash veya onboarding’de arka planda çağırın.
Android implementasyon iskeleti
Codegen base class’a extend edersiniz — elle JNI binding yazmazsınız:
public class NativeSampleModule extends NativeSampleModuleSpec {
public NativeSampleModule(ReactApplicationContext ctx) {
super(ctx);
}
@Override
public double add(double a, double b) {
return a + b;
}
@Override
public void fetchToken(String userId, Promise promise) {
// async: native thread'de iş, promise resolve/reject
}
}
iOS’ta generated Spec protocol’ü implement edilir. Android + iOS davranış parity testleri şart.
Eski Native Module’den migrasyon
- Mevcut API yüzeyini Spec’e dökün — deprecated metotları şimdi kaldırın
- Android/iOS implementasyon yazın; E2E ile doğrulayın
- JS import:
NativeModules.Foo→ Spec default export - Feature flag ile eski/yeni paralel (riskli modüller)
- Event listener audit:
addListener/removeListeners - ProGuard keep: generated sınıflar
Interop geçici köprüdür — yeni modül eklemeyin; migrate edin.
Sık hatalar
- Spec’te
number, native’deint/long/doublekarışıklığı - Event listener remove etmemek → leak
- Codegen adı ile registry string uyuşmazlığı
- Turbo Module yazıp Fabric component unutmak (view’lar ayrı Spec)
- Sync metotları her yere yaymak
- New Arch kapalı ortamda test etmemek
Production checklist
-
codegenConfigdoğru; CI’da çıktı doğrulanıyor - Spec tek kaynak
- Sync metotlar auditlendi
- Init side-effect yok veya explicit
warmup()var - Android + iOS aynı davranış testleri
- Event listener lifecycle test edildi
- New Arch kapalı interop smoke (geçiş dönemi)
- ProGuard keep generated sınıfları kapsıyor
Özet
Turbo Modules, native sınırı dokümantasyondan çıkarıp derleyiciye verir. Performans JSI’den, güvenilirlik codegen’den, startup lazy init’ten gelir. Spec’i API review sürecine dahil edin; her native metot ekleme PR’da Spec diff’i olsun.