React Native uzun süre bridge (JS ile native arasındaki eski iletişim köprüsü) üzerine kuruldu. JavaScript bir mesaj kuyruğuna JSON yazar, native taraf okur, sonucu yine asenkron geri yollardı. Bu model ekosistemi büyüttü; ama animasyon gibi sık native çağrı isteyen işlerde tavanı erken gösterdi.
New Architecture ile gelen bridgeless modelde merkezi JSON köprüsü kalkar. Hermes (React Native’in JS motoru) ile native kod JSI (JavaScript Interface — doğrudan çağrı katmanı) üzerinden konuşur.
Klasik bridge: basit ama pahalı
Bridge modelinde native modül çağrısı şöyle akar:
- JS,
NativeModules.Foo.bar(args)çağırır. - Argümanlar JSON’a çevrilir (serileştirme maliyeti).
- Mesaj asenkron kuyruğa girer.
- Native metot çalışır; dönüş yine Promise/callback ile serileştirilir.
Artı: iki dünya arasında net sınır, kolay anlama. Eksi: her çağrıda sabit vergi — serileştirme CPU’su, kuyruk gecikmesi, batching yan etkileri.
Somut maliyetler
- Serileştirme: Büyük obje veya saniyede yüzlerce küçük çağrı hem JS hem native thread’i yorar.
- Asenkronluk: Animasyon ve gesture için 16ms frame bütçesine bridge gidiş-gelişi sığmayabilir.
- Batching: Bir frame’de biriken mesajlar scroll takılmasına yol açabilir.
- Zayıf tip güvenliği: Yanlış method adı production’da sürpriz olur.
- Erken yükleme: Kullanılmayan SDK bile cold start’ı şişirebilir.
Reanimated’ın JSI’ye geçmesi tesadüf değildi: animasyon state’ini UI thread’e taşımak için doğrudan çağrı gerekti.
Bridgeless ne demek?
Bridgeless, “native iletişim yok” demek değildir. Anlamı: merkezi JSON köprüsü yok; JS runtime ile native kod JSI üzerinden host object (JS’te görünen native nesne) ile bağlanır.
New Architecture parçaları bu modeli tamamlar:
- Turbo Modules: Native API’ler JSI host object; lazy init (ilk çağrıda yükleme), codegen Spec.
- Fabric: C++ shadow tree; çizim bridge trafiğinden çıkar.
- Interop: Eski bridge modülleri geçişte çalışır — kalıcı çözüm değildir.
Sync çağrı: mümkün mü?
JSI ile senkron native çağrı mümkündür. Eski bridge’de neredeyse her şey async’ti; “native’den flag oku” bile Promise zinciri isterdi. MMKV, Reanimated shared value gibi kütüphaneler bu yüzden sync JSI sunar.
Dikkat: Sync çağrı JS thread’i bloklar. Disk, ağ veya ağır hesap sync yapılmamalı. Sync yalnızca kısa, ölçülmüş okumalar için.
İki modelin karşılaştırması
| Boyut | Bridge | Bridgeless |
|---|---|---|
| Çağrı modeli | Async JSON kuyruk | JSI doğrudan binding |
| Serileştirme | Her çağrıda | Primitive ve Spec tipleri optimize |
| Tip sözleşmesi | Runtime keşif | Codegen + Spec |
| Startup | Erken modül yükleme | Lazy init |
| Animasyon | Kırılgan | Worklet + Fabric ile uyumlu |
| Kütüphane uyumu | Eski modüller hazır | New Arch desteği şart |
Bridgeless otomatik “2x FPS” demek değildir. Gereksiz re-render veya kötü liste virtualization mimariyle kaybolmaz. Kazanç, sık native çağrılarda ve UI tutarlılığındadır.
Bridge kalıntısı ne zaman ısırır?
- Doğrudan
NativeModules.Xkullanımı — interop beklenenden farklı davranabilir. - New Arch uyumsuz kütüphane — uygulama açılır, kamera/ödeme ekranı crash eder.
- “New Arch açtık, her şey düzelir” varsayımı — bottleneck JS veya network ise mimari sihir işlemez.
- Sync abuse — her şeyi sync yazmak ANR ve frame drop üretir.
Interop geçişi hızlandırır ama “migrate olduk” illüzyonu yaratır. Hangi modüllerin hâlâ bridge üzerinden konuştuğunu listeleyin.
Migrasyon: pratik sıra
- Bağımlılık matrisi: Her native lib için Fabric / Turbo / bridgeless notu.
- İç modülleri Spec’e taşı:
NativeModulesimport’larını codegen Spec’e çevirin. - Platform bazlı açılış: Android önce sık tercih edilir; iOS Pod clean daha pahalıdır.
- Hassas akışları E2E’ye alın: Gesture, kamera, ödeme, harita, push.
- Metrik baseline: JS FPS, UI FPS, cold start, crash-free.
- Rollback binary:
newArchEnabled=falseaynı commit’ten üretilebilmeli.
Kritik: New Architecture OTA ile geri alınamaz. Yanlış giden Fabric bug’ı store binary ister.
Interop’u kalıcı çözüm sanmayın. Her sprint’te N modülü Spec’e taşıyın; yeni kod interop’a eklenmemeli.
Performans: ne izlemeli?
- Performance Monitor: JS FPS ile UI FPS’i ayrı bakın.
- Systrace / Perfetto (Android), Instruments (iOS): Kuyruk derinliği, mount süreleri.
- Production cohort: New Arch açık %5 vs kontrol grubu crash-free ve ANR.
Scroll listesi, gesture-heavy ekran ve cold start ayrı benchmark olsun.
Production checklist
- Hangi modüller hâlâ
NativeModuleskullanıyor? - Hangileri Turbo Module Spec’e geçti?
- Bridgeless açıkken interop uyarıları izleniyor mu?
- JS FPS / UI FPS baseline alındı mı?
- Crash-free oran New Arch cohort’unda karşılaştırılıyor mu?
- Rollback binary pipeline’da hazır mı?
- OTA planı native mimari değişikliği içermiyor mu?
Özet
Bridge, React Native’i mümkün kılan basitlikti; bridgeless, sık native etkileşim için gerekli adımdır. Soru “bridge kötü mü?” değil: hangi çağrı hâlâ JSON kuyruğunda, hangisi JSI’ye taşınmalı? New Architecture bu sorunun ürünleşmiş cevabıdır. Migrasyon maliyeti gerçektir; plansız açılış production post-mortem’ine giden kısa yoldur.