Bridge, React Native’in JavaScript iş parçacığı ile iOS ve Android’in yerel ortamı arasında asenkron iletişim sağlayan mimari bir bileşenidir. Bir kuyruk aracılığıyla serileştirilmiş JSON mesajları iletir ve JS kodundan yerel API’lerin çağrılmasına olanak tanır. Meta, 2024’e göre, Bridge mevcut uygulamaların temeli olmaya devam etmektedir, ancak JSI üzerindeki yeni mimariye göre performansta geride kalmaktadır.
Önemli Noktalar
Bridge, React Native’in önemli bir mimari öğesidir ve uygulamanın iş mantığının çalıştırıldığı JavaScript iş parçacığı ile yerel iOS ve Android iş parçacıkları arasında çift yönlü asenkron iletişim sağlar. React Native’in 2015’te piyasaya sürülmesinden bu yana Bridge, JS kodunun platform API’leriyle — kamera, coğrafi konum, dosya sistemi, bildirimler ve diğer yerel yetenekler — etkileşime girmesinin tek yolu olmuştur.
Bridge mimarisi, mesaj kuyruğu (message queue) ilkesine dayanır. JavaScript kodu yerel bir metodu çağırdığında, istek bir JSON dizesine serileştirilir, bir kuyruğa konulur ve asenkron olarak yerel tarafa gönderilir. Yerel kod isteği işler, ilgili işlemi gerçekleştirir ve sonucu aynı kuyruk aracılığıyla JS iş parçacığına geri gönderir. Meta’nın React Conf 2021’deki raporuna göre, ortalama bir uygulamada saniyede 10.000 mesaja kadarı Bridge’den geçmektedir.
Bridge çalışmasında yer alan ana iş parçacıkları: JavaScript Thread (JS kodu yürütme), Native Thread (yerel işlemleri yürütme) ve Shadow Thread (Yoga ile düzen hesaplama). Her iş parçacığı bağımsız çalışır ve UI’nun yanıt verebilirliğini sağlar — yerel animasyonlar JS hesaplamaları tarafından engellenmez.
Bridge, iletişim için üç temel mekanizma kullanır: MessageQueue, JSON serileştirme ve mesaj toplulaştırma (batching). MessageQueue, JS ile yerel taraf arasındaki çağrı kuyruğunu yöneten dahili bir React Native bileşenidir. Her yerel metot çağrısı bir kuyruğa konulur, serileştirilir ve performans optimizasyonu için toplu olarak gönderilir.
MessageQueue, toplulaştırma ilkesiyle çalışır: yerel metot çağrıları birikir ve her 5–15 milisaniyede bir tek bir grup (toplu) olarak gönderilir. Bu, serileştirme yükünü azaltır çünkü birden çok çağrı tek bir JSON paketine paketlenir. Yerel tarafta, mesajlar seri durumdan çıkarılır ve ilgili modüllere dağıtılır.
Yerel modüller, makrolar veya açıklamalar aracılığıyla otomatik olarak kaydedilir. iOS, RCT_EXPORT_MODULE makrosunu kullanır, Android ise @ReactMethod açıklamasını kullanır. React Native, uygulama başlatılırken kayıtlı modülleri tarar ve mevcut tüm metotların bir yapılandırma JSON haritasını oluşturur. Bu harita JS ortamına iletilir ve JavaScript hangi metotların çağrılabileceğini öğrenir.
Veriler şu yolu izler: JavaScript, NativeModules.CalendarModule.createCalendarEvent() çağrısını yapar. Metot, modül tanımlayıcısı, metot adı ve bağımsız değişkenlerle birlikte bir JSON mesajına serileştirilir. Mesaj MessageQueue’ya girer. Yerel iş parçacığında mesaj seri durumdan çıkarılır ve ilgili modüle iletilir. Yürütme sonucu tekrar serileştirilir ve JS iş parçacığına Promise veya callback olarak gönderilir.
// JavaScript'ten Bridge üzerinden yerel modül çağrısı
import { NativeModules } from 'react-native';
const CalendarModule = NativeModules.CalendarModule;
CalendarModule.createCalendarEvent('Test Event', 'Office')
.then(eventId => {
console.log('Oluşturulan etkinlik kimliği:', eventId);
})
.catch(error => {
console.error('Başarısız:', error);
});
Yerel iOS tarafında, modül RCT_EXPORT_MODULE makrosuna sahip bir Objective-C sınıfı olarak görünür. Metot, RCT_EXPORT_METHOD makrosu kullanılarak dışa aktarılır ve React Native bunu otomatik olarak Bridge’e kaydeder. Bağımsız değişkenler konuma göre iletilir ve desteklenen JSON türlerine (NSString, NSNumber, NSArray, NSDictionary, BOOL) karşılık gelmelidir.
// Bridge'te iOS Yerel Modül Kaydı
@interface CalendarModule () RCT_EXPORT_MODULE()
@end
@implementation CalendarModule
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name
location:(NSString *)location
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSNumber *eventId = createEvent(name, location);
resolve(eventId);
}
@end
Bridge’in bir dizi temel performans sınırlaması vardır. Bunlardan en önemlisi zorunlu asenkronluk ve serileştirmedir. Her yerel metot çağrısı verileri bir JSON dizesine dönüştürür, bu da gecikme ekler ve bellek tüketir. Görüntü işleme veya video ile çalışma gibi büyük veri hacimli işlemler için bu bir darboğaz haline gelir.
JSON serileştirme ve seri durumdan çıkarma, CPU zamanı ve bellek tüketir. Her mesajın JS tarafında bir dizeye dönüştürülmesi, köprü üzerinden iletilmesi ve yerel tarafta ayrıştırılması gerekir. Callstack testlerine (2022) göre, Bridge üzerinden 10.000 sayılık bir diziyi serileştirmek yaklaşık 30–50 milisaniye sürmektedir ve bu, yüksek frekanslı çağrılar için kabul edilemez.
Bridge, büyük ikili verilerin aktarımı için optimize edilmemiştir. Fotoğraflar, ses dosyaları ve video akışları alternatif yaklaşımlar gerektirir — örneğin, bir dosyayı diske yazmak ve yolu bir dize olarak iletmek. Bu, dosya sistemi okuma ve yazma işlemlerinde ek yük oluşturur.
Bu sınırlamaların farkına varılması, Meta ekibini Bridge’in JSI (JavaScript Interface) ve Turbo Module ile değiştirildiği yeni bir React Native mimarisi geliştirmeye yönlendirdi. JSI, serileştirme olmadan yerel metotları doğrudan çağırmaya olanak tanıyarak Bridge’in ana dezavantajını ortadan kaldırır.
Bridge ve Turbo Module karşılaştırması, mimari yaklaşımlardaki temel farklılıkları gösterir. Bridge, JSON serileştirme ile asenkron bir mesaj kuyruğu kullanırken, Turbo Module JSI aracılığıyla çalışır — JavaScript ve C++ arasında, veri dönüşümü olmadan yerel metotları senkron olarak çağırmaya olanak tanıyan doğrudan bir arayüz.
| Özellik | Bridge | Turbo Module |
|---|---|---|
| Çağrı Türü | Asenkron | Senkron ve asenkron |
| Serileştirme | Her çağrıda JSON | Kopyasız JSI nesneleri |
| Performans | Orta | Yüksek |
| Tipler | Dinamik | Statik (Codegen) |
| Yükleme | Başlatmada tüm modüller | Tembel (istek üzerine) |
Bridge ve Turbo Module arasındaki seçim, React Native sürümüne bağlıdır. React Native 0.72 ve öncesi projeler için Bridge ana mekanizma olmaya devam etmektedir. React Native 0.73’ten itibaren, Metro ve yeni mimari paralel olarak desteklenmekte ve kademeli geçişe olanak tanımaktadır. Turbo Module’e tam geçiş, React Native 0.76+’ya güncelleme ve yapılandırmada yeni mimarinin etkinleştirilmesini gerektirir.
Bir takvim modülü örneğini kullanarak Bridge üzerinden bir Native Module oluşturma ve kullanma döngüsünü inceleyelim. Modül bir etkinlik oluşturacak ve tanımlayıcısını döndürecektir. Bu örnek, her iki platform — iOS ve Android için kurulumu kapsar.
Android’de bir Native Module, ReactContextBaseJavaModule’ı genişleten bir Java sınıfı olarak oluşturulur. @ReactMethod açıklaması metodu Bridge’e aktarır. Promise için com.facebook.react.bridge’den Promise arayüzü kullanılır.
public class CalendarModule extends ReactContextBaseJavaModule {
@Override
public String getName() {
return "CalendarModule";
}
@ReactMethod
public void createCalendarEvent(
String name,
String location,
Promise promise) {
try {
Integer eventId = createCalendarEventNative(name, location);
promise.resolve(eventId);
} catch (Exception e) {
promise.reject("EVENT_ERROR", e.getMessage());
}
}
}
Modül, @ReactModule aracılığıyla veya uygulama paketinde manuel olarak kaydedilir. React Native onu otomatik olarak algılar ve Bridge’e ekler. Kayıttan sonra modüle JavaScript’ten NativeModules aracılığıyla erişilebilir.
public class CalendarPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
return Arrays.asList(
new CalendarModule(reactContext)
);
}
@Override
public List<ViewManager> createViewManagers(
ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
Yeni modüller eklenirken Bridge’in uygulamanın yeniden başlatılmasını gerektirdiğini unutmamak önemlidir, çünkü yapılandırma haritası başlatma sırasında bir kez oluşturulur. Bu, onu tembelce yüklenen ve yeniden başlatma olmadan modüllerin sıcak yeniden yüklenmesini destekleyen Turbo Module’den ayırır.
Sıkça Sorulan Sorular
Bridge her zaman asenkron bir kuyruk ve JSON serileştirme kullanırken, JSI aracılığıyla doğrudan aktarım senkron olarak ve veri kopyalamadan çalışır. Bridge serileştirme gecikmesi yaratır ancak iş parçacığı yalıtımını sağlar.
Hayır, Bridge yalnızca asenkron çağrıları destekler. Senkron etkileşim için JSI ve Turbo Module ile yeni mimari gereklidir. Bu, React Native 0.76+’da çözülmüş temel sınırlamalardan biridir.
Bridge, JSON’da serileştirilebilir türleri destekler: dizeler, sayılar, boolean değerler, diziler, sözlükler (nesneler). Görüntüler gibi ikili veriler, dosya sistemi veya base64 kodlaması aracılığıyla aktarılmalıdır.
Ölçüm için React DevTools ve React Native profilleyicisini kullanın. Performance sekmesi, Bridge kuyruğundaki mesaj sayısını ve gecikmeleri gösterir. Trafik izleme için react-native-bridge-spy paketi de mevcuttur.
Performans gerektiren projeler için veya React Native 0.76+’da yeni uygulamalar oluştururken geçiş önerilir. Mevcut projeler için geçiş kademeli olabilir — her iki mimari de paralel çalışır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun