Tüm Yazılar
KategoriReact Native
Okuma Süresi
13 dk
Yayın Tarihi
2025-10-30
Kelime Sayısı
2.734kelime

Kahveni hazırla - bu içerikli bir makale!

React Native Render Performansı: Boost ve Native Wrapper

Özet

React Native render performansı için react-native-boost'un native wrapper maliyetini nasıl azalttığını, sınırlarını ve önce/sonra ölçüm protokolünü uygulamalı olarak görüyorsun.

  • react-native-boost, Text/View bileşenlerinin native wrapper katmanını derleme zamanında Babel AST analiziyle sadeleştiriyor.
  • 2025-10-30 itibarıyla geçerli sürüm v0.6.2 idi; entegrasyon yalnızca babel.config.js plugins dizisine eklemekten ibaretti.
  • Kazanç, derin ve tekrarlı ağaçlarda (uzun liste, kart grid) anlamlı; basit statik ekranlarda ölçüm gürültüsüne karışabiliyor.
  • v2.0.0 (13 Eylül 2026) ile entegrasyon Metro config plugin mimarisine taşındı ve kapsam Text/View'in ötesine genişledi.
React Native Render Performansı: Boost ve Native Wrapper

React Native render performansı konuşulduğunda çoğu ekip önce Hermes'i, sonra da yeni mimariyi (Fabric) gündeme getirir; ama ekranda görünen her <View> ve <Text>'in JavaScript'ten native tarafa gidene kadar geçtiği ara katmanlar da render maliyetinin önemli bir parçasıdır. react-native-boost gibi bir Babel eklentisi tam olarak burada devreye giriyor: derleme zamanında bileşen ağacını analiz edip gereksiz native wrapper'ları eleyerek çalışma zamanı yükünü azaltmayı hedefliyor. Bu yazıda react-native-boost'un 2025-10-30 itibarıyla ne yaptığını, sınırlarını ve ölçüm protokolünü uygulamalı şekilde ele alıyorsun.

💡 Pro Tip: Optimizasyonu üretime almadan önce paketi yalnızca en pahalı ekranda (uzun liste, ağır grid) opt-in olarak dene; tüm uygulamaya tek seferde uygulamak, kazancı gürültüden ayırt etmeni zorlaştırır.

İçindekiler

RN'de bir bileşenin ekrana gelene kadarki yolu

React Native'de yazdığın <View> ya da <Text> bileşeni doğrudan native görünüme dönüşmez. JavaScript tarafında React, bir element ağacı (reconciliation) üretir; bu ağaç köprü (bridge) ya da yeni mimaride JSI üzerinden native tarafa taşınır ve orada gerçek UIView (iOS) ya da native View (Android) nesnelerine karşılık gelir. Bu zincirde her bileşen için ayrı bir native karşılık oluşturulması, ağaç derinleştikçe kurulum ve düzen (layout) maliyetini büyütür.

React Native'in kendi Text ve View bileşenleri de bu zincirin dışında değil: ikisi de kullanıcı kodunun üstünde ince bir sarmalayıcı (wrapper) katmanı olarak çalışır ve bu sarmalayıcı, kendi render mantığını (prop işleme, native bileşen eşleme) her render'da yeniden çalıştırır.

Bu ara katmanın var oluş nedeni geliştirici deneyimi: Text bileşeni, altına ekstra platform-spesifik davranış (metin seçimi, erişilebilirlik prop'ları, varsayılan stil kalıtımı) ekleyebilmek için kendi sarmalayıcısını taşıyor; View de benzer şekilde layout ve stil normalizasyonunu tek noktadan yönetiyor. Bu, günlük geliştirme sırasında fark edilmeyen bir maliyet — çünkü tek bir Text örneğinde sarmalayıcının çalışma süresi mikrosaniyeler mertebesinde. Sorun, bu mikro maliyetin bileşen sayısıyla çarpılarak birikmesinde: bir ekranda yüzlerce Text/View örneği varsa, her birinin kendi sarmalayıcı mantığını çalıştırması toplam render bütçesinin gözle görülür bir kısmını tüketebiliyor.

Bu sarmalayıcı, geliştirici deneyimi açısından değerli: prop validasyonu, platformlar arası tutarlılık ve varsayılan davranışlar sağlıyor. Ama derin ve tekrarlı ağaçlarda (uzun liste satırları, kart gridleri) her Text/View örneğinin kendi wrapper mantığını tekrar tekrar çalıştırması, toplamda ölçülebilir bir render yükü biriktiriyor. react-native-boost'un çıkış noktası tam olarak bu gözlem: bu sarmalayıcının derleme zamanında güvenle atlanabileceği durumları statik analizle tespit etmek.

Wrapper maliyeti nerede birikiyor

Wrapper maliyeti tek bir bileşende görünmez; birikimli bir etkidir. Üç yerde katmanlaşır:

  • Kurulum (mount) anında: Her Text/View örneği ilk render'da kendi iç mantığını çalıştırır — bu maliyet bileşen sayısıyla doğru orantılı olarak birikir; derin ve tekrarlı ağaçlarda tekrar sayısı büyüdüğü için toplam da büyür.
  • Yeniden render'da: State değişimi ağacın üst kısmında olsa bile, aradaki her wrapper kendi reconciliation adımından geçer.
  • Bellek ayak izinde: Her sarmalayıcı örneği, native karşılığına ek olarak kendi JS tarafı nesnesini de tutar.

react-native-boost'un dokümantasyonu, Text ve View'ın aslında kendi native karşılıkları olan TextNativeComponent ve ViewNativeComponent etrafında JavaScript tabanlı sarmalayıcılar olduğunu belirtiyor ("Text and View are actually JavaScript-based wrappers around their native counterparts, TextNativeComponent and ViewNativeComponent"); proje 23 Şubat 2025'te oluşturuldu ve o dönemde README'de paketin hâlâ deneysel olduğu uyarısı yer alıyordu. Bu, paketin production'a alınmadan önce dikkatli test edilmesi gerektiği anlamına geliyor — özellikle özel Text/View alt sınıflaması yapan (custom prop forwarding, ref-forwarding) kod tabanlarında.

react-native-boost'un yaptığı dönüşüm ve sınırları

react-native-boost bir çalışma zamanı kütüphanesi değil, bir Babel eklentisi: derleme sırasında AST (soyut sözdizim ağacı) üzerinde statik analiz yaparak, güvenle sadeleştirilebilecek Text/View kullanımlarını tespit ediyor ve bunları runtime paketinden yeniden dışa aktarılan (re-export) daha hafif karşılıklarla değiştiriyor. Wayback Machine'deki 14 Ağustos 2025 tarihli arşiv kaydına göre mekanizma şu adımlardan oluşuyor:

  1. Babel, kod tabanındaki Text/View kullanımlarını AST seviyesinde tarar.
  2. Güvenli olduğu belirlenen kullanımlar, runtime paketinden re-export edilen sadeleştirilmiş bileşenlerle değiştirilir.
  3. Bu değişim, component tree'nin bazı katmanlarını düzleştirerek (flattening) native tarafa taşınan ara adım sayısını azaltır.

2025-10-30 tarihinde geçerli sürüm v0.6.2 idi ve entegrasyon babel.config.js dosyasına eklenen react-native-boost/plugin girdisiyle yapılıyordu:

js
1// babel.config.js — react-native-boost v0.6.2 (2025-10-30 itibarıyla)
2module.exports = {
3 plugins: ["react-native-boost/plugin"],
4};

O tarihte v0.6.2 manifestindeki peerDependencies alanı react-native: "*" idi; beyan edilmiş bir minimum RN sürümü şartı yoktu. Dokümantasyon o dönemde react-native-boost.oss.kuatsu.de adresinde yayındaydı.

Sınırlar — statik analiz kullanan her araçta olduğu gibi:

  • Sarmalayıcının kaldırılması güvenle belirlenebildiğinde çalışır; dinamik/koşullu prop-forwarding yapan özel sarmalayıcılar analiz dışında kalabilir.
  • MIT lisanslı, açık kaynak bir eklenti olarak bakım hızı topluluğa bağlı; büyük RN sürüm sıçramalarında (yeni mimari değişiklikleri gibi) uyumluluk penceresi gecikmeli kapanabilir.
  • Paket yalnızca Text ve View'a odaklanıyordu (2025-10-30 itibarıyla); Animated, ActivityIndicator, StyleSheet gibi diğer çekirdek bileşenler bu sürümde kapsam dışıydı.

Ölçüm: önce/sonra profil çıkarma protokolü

Bir derleme-zamanı optimizasyonunun gerçek etkisini görmek için "hissi" değil, ölçülebilir bir protokol kullanman gerekiyor. Aşağıdaki adımlar, React Native'in resmi Profiling dokümanının önerdiği native ölçüm yaklaşımını (iOS'ta Instruments, Android'de Android Studio Profiler/System Tracing) ve React Native DevTools'un React Profiler panelini birlikte kullanıyor:

  1. Baseline ölç: react-native-boost eklenmeden önce, en pahalı ekranı (uzun FlatList, kart grid'i) React DevTools Profiler ile kaydet — commit sayısı ve commit başına süreyi not et.
  2. Eklentiyi opt-in ekle: babel.config.js'e yalnızca plugins dizisine ekleme yaparak devreye al, kod tabanında başka değişiklik yapma.
  3. Metro cache'i temizle:
bash
1# Babel eklentisi değişikliği cache'lenmiş bundle'a yansımaz
2npx react-native start --reset-cache
  1. Aynı senaryoyu aynı cihazda tekrar ölç: Aynı ekran, aynı veri seti, aynı fiziksel cihaz (simülatör değil) — commit süresi ve JS thread FPS'ini karşılaştır.
  2. Regresyon testi çalıştır: Statik analiz false-positive üretmiş olabilir; snapshot testleri ve manuel görsel kontrol (özellikle özel Text alt sınıfları) bu adımda kritik.

Basit bir profil betiği

Kaydettiğin commit sürelerini karşılaştırmak için React DevTools Profiler'ın dışa aktardığı JSON'u basitçe özetleyebilirsin:

ts
1// profile-summary.ts — Profiler export JSON'undan ortalama commit süresi
2import fs from "node:fs";
3 
4type CommitDataExport = { duration: number };
5type ProfilingDataForRootExport = { commitData: CommitDataExport[] };
6type ProfilingDataExport = { version: number; dataForRoots: ProfilingDataForRootExport[] };
7 
8function averageCommitDuration(path: string): number {
9 const raw = fs.readFileSync(path, "utf8");
10 const data = JSON.parse(raw) as ProfilingDataExport;
11 const allCommits = data.dataForRoots.flatMap((root) => root.commitData);
12 const total = allCommits.reduce((sum, c) => sum + c.duration, 0);
13 return total / allCommits.length;
14}
15 
16console.log(
17 "Ortalama commit süresi (ms):",
18 averageCommitDuration(process.argv[2]),
19);

Bu betik somut bir sayı üretmiyor — kendi ekranından topladığın gerçek Profiler exportuyla çalıştırman gerekiyor. Bağımsız bir üçüncü-taraf ölçümü yok; üreticinin kendi benchmark sayfası iOS ve Android'de %50'ye varan iyileşme bildiriyor (bağımsız doğrulanmadı).

Native tarafta destekleyici bir ikinci ölçüm

JS tarafındaki Profiler verisini tek başına yeterli görmemeni öneririm; native tarafta da bir doğrulama yapman, ölçtüğün farkın gerçekten render katmanından mı yoksa başka bir sebepten mi (ağ gecikmesi, resim decode süresi) geldiğini ayırt etmene yardımcı oluyor. Bunun için basit bir yardımcı fonksiyon, ekran geçişleri arasındaki süreyi native taraftan da işaretlemene imkân veriyor:

ts
1// screen-marks.ts — ekran geçişi zaman damgalarını konsola yazan basit yardımcı
2type ScreenMark = { name: string; ts: number };
3 
4const marks: ScreenMark[] = [];
5 
6export function markScreen(name: string): void {
7 marks.push({ name, ts: Date.now() });
8}
9 
10export function diffMarks(fromName: string, toName: string): number | null {
11 const from = marks.find((m) => m.name === fromName);
12 const to = marks.find((m) => m.name === toName);
13 if (!from || !to) return null;
14 return to.ts - from.ts;
15}

Bu yardımcıyı ekranın mount ve interactive anlarında çağırarak, Profiler'daki commit süresiyle çapraz kontrol edebilirsin — ikisi aynı yönde hareket ediyorsa (optimizasyon sonrası ikisi de düşüyorsa) ölçtüğün farkın gerçek olma ihtimali artıyor.

Hangi ekranlarda kazanç anlamlı, hangilerinde gürültü

Statik bir sarmalayıcı kaldırma optimizasyonunun etkisi, ağacın derinliğiyle ve tekrar sayısıyla doğru orantılı büyüyor:

Ekran türü
Wrapper tekrar sayısı
Beklenen kazanç sinyali
Uzun FlatList/FlashList satırları
Yüksek (yüzlerce örnek)
Anlamlı — commit süresi farkı ölçülebilir
Kart grid'i (dashboard, katalog)
Orta-yüksek
Anlamlı, ekran karmaşıklığına bağlı
Form ekranı (birkaç Text/View)
Düşük
Gürültü seviyesinde, ölçüm hatasına karışabilir
Tek seferlik modal/onboarding
Düşük
Gürültü seviyesinde
Özel Text alt sınıflaması yoğun ekranlar
Değişken
Statik analiz bu bileşenleri atlayabilir — kazanç sıfıra yakın olabilir

Kısacası: az sayıda, sık tekrar eden bileşenden oluşan derin listelerde anlamlı bir sinyal bekleyebilirsin; birkaç düzine bileşenlik statik ekranlarda ölçüm gürültüsünün gerçek kazancı gölgelemesi olası. Bu yüzden "Ölçüm: önce/sonra profil çıkarma protokolü" bölümündeki adımları her zaman en pahalı ekranda çalıştırmak, genel "uygulamaya taktım, hızlandı" izlenimine göre çok daha güvenilir bir karar temeli veriyor.

Yeni mimariyle (Fabric) ilişkisi

React Native'in resmi mimari dokümantasyonu Fabric'i React Native'in yeni render sistemi olarak tanımlıyor; çekirdek ilkeleri render mantığının daha fazlasını C++'ta birleştirmek, host platformlarla birlikte çalışabilirliği artırmak ve yeni yeteneklerin önünü açmak. Bu, react-native-boost'un çözdüğü sorunla aynı katmanda değil ama komşu bir katmanda duruyor: Fabric, JS-native iletişiminin nasıl yapıldığını değiştirirken; react-native-boost, JS tarafındaki bileşen ağacının ne kadar iş yaptığını azaltıyor. İkisi birbirini dışlamıyor — Fabric aktif bir projede de gereksiz Text/View sarmalayıcıları hâlâ derleme zamanında sadeleştirilebilir.

Bu ayrımı unutmamak önemli: Fabric'e geçmek tek başına wrapper maliyetini sıfırlamıyor; sen hâlâ derin bir Text/View ağacı yazıyorsan, bu ağaç Fabric altında da JS tarafında reconciliation'dan geçiyor. Derleme zamanı optimizasyonu ile mimari değişikliği birbirini tamamlayan, birbirinin yerine geçmeyen iki farklı araç.

Uygulamadan önce kontrol listesi

  • Sürüm uyumluluğunu kontrol et: Kullandığın react-native-boost sürümünün RN sürümünle uyumluluğunu README'den doğrula — sürümler arasında minimum RN şartı değişebiliyor.
  • Metro cache'i temizleyerek test et: --reset-cache olmadan yaptığın ölçüm yanıltıcı olabilir.
  • Özel Text/View sarmalayıcılarını gözden geçir: Prop-forwarding yapan özel bileşenlerin statik analizden nasıl etkilendiğini manuel kontrol et.
  • Baseline'ı kaydet: Eklentiyi açmadan önce Profiler exportunu sakla — karşılaştırma yapamazsan "hızlandı" hissi bir varsayımdan öteye geçemez.
  • Snapshot testlerini çalıştır: Statik dönüşüm, render çıktısında beklenmeyen bir farka yol açmışsa snapshot testleri bunu ilk yakalayan katman olur.
  • Kademeli devreye al: Tüm uygulamada değil, önce tek bir ekranda (en pahalı liste/grid) test et.
  • Geri alma planını hazırla: Entegrasyon tek satırlık bir babel.config.js değişikliği olduğu için geri alma da aynı derecede basit olmalı — bir sorun tespit edersen plugins dizisinden satırı kaldırıp Metro cache'ini yeniden temizlemen yeterli.
  • CI'da da doğrula: Yerel makinende çalışan bir derleme, CI'daki temiz ortamda farklı davranabilir; en azından bir CI derlemesinde de eklentinin sorunsuz derlendiğini teyit et.

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

Bu optimizasyonu güvenle devreye almadan önce kendine sorman gereken sorular var; aşağıdaki listeyi yeni bir eklenti veya derleme-zamanı araç eklerken genel bir kontrol listesi olarak da kullanabilirsin.

SSS

React Native render performansı nasıl artırılır?

Render performansını artırmanın birden fazla katmanı var: JS tarafında gereksiz re-render'ları önlemek (memoization, doğru key kullanımı), derleme zamanında gereksiz sarmalayıcıları azaltmak (react-native-boost gibi Babel eklentileri) ve mimari seviyede JS-native iletişimini hızlandırmak (Fabric/JSI). react-native-boost özellikle ikinci katmana odaklanıyor: derin Text/View ağaçlarında statik analizle gereksiz sarmalayıcıyı kaldırıyor.

Text ve View wrapper'ları neden maliyetli?

React Native'in Text ve View bileşenleri, kullanıcı kodunun üstünde ince bir sarmalayıcı katmanı olarak çalışır; her örnek kendi prop işleme ve native bileşen eşleme mantığını taşır. Ağaç derinleştikçe ve tekrar sayısı arttıkça (uzun listeler, kart gridleri) bu sarmalayıcıların toplam çalışma zamanı yükü birikimli hale gelir — tek bir örnekte fark edilmez ama yüzlerce örnekte ölçülebilir olur.

Bu optimizasyon hangi durumda işe yaramaz?

Statik analizin sarmalayıcıyı güvenle kaldıramadığı durumlarda (özel prop-forwarding yapan Text/View alt sınıfları) kazanç sınırlı kalabilir. Ayrıca az sayıda bileşenden oluşan basit ekranlarda (form, tek modal) kazanç ölçüm gürültüsüne karışacak kadar küçük olabilir — bu yüzden protokolü her zaman en pahalı ekranda çalıştırmak gerekiyor.

react-native-boost'u devreye almak kod tabanında değişiklik gerektirir mi?

2025-10-30 itibarıyla hayır — entegrasyon yalnızca babel.config.js dosyasındaki plugins dizisine react-native-boost/plugin eklemekten ibaretti; bileşen kodlarında manuel bir değişiklik gerekmiyordu. Statik analiz derleme zamanında otomatik çalışıyor.

Fabric'e geçtiysem bu optimizasyona ihtiyacım var mı?

Evet, potansiyel olarak — Fabric, JS ile native taraf arasındaki iletişim hattını değiştiriyor ama JS tarafındaki bileşen ağacının boyutunu küçültmüyor. Derin Text/View ağaçların varsa, Fabric aktifken de derleme zamanı sadeleştirmesi ayrı bir kazanç katmanı olarak kalıyor.

Güncelleme (Eylül 2026)

Bu yazının gövdesi 2025-10-30 tarihli v0.6.2 sürümünü esas alıyor. GitHub release kayıtlarına göre paket o tarihten bugüne kadar önemli ölçüde geliştirildi:

  • v1.0.0 (27 Şubat 2026): Paket 1.x kararlı hattına geçti (ilk majör sürüm).
  • v1.6.0 (11 Temmuz 2026): İlk opt-in Image optimizer'ı ve metin eşleme (text-parity) düzeltmeleri eklendi.
  • v1.7.0 / v1.7.1 (3 Eylül 2026): RN 0.86 desteği geldi; Image optimizer varsayılan davranışa terfi etti.
  • v2.0.0 (13 Eylül 2026): Mimari sıçrama — entegrasyon yöntemi Babel plugin'den Metro config plugin'e taşındı (elle migrasyon gerektiriyor); 5 yeni optimizer eklendi (Animated, ActivityIndicator, StyleSheet, Platform ve diğer kod dönüşümleri için); uzun süredir beklenen Uniwind desteği geldi; RN 0.88 RC ile uyumluluk doğrulandı.
  • v2.0.1 (14 Eylül 2026) / v2.0.2 (18 Eylül 2026): Küçük düzeltme sürümleri.
Sürüm
Tarih
Öne çıkan değişiklik
v0.6.2
2025-06-11 (bu yazının esas aldığı sürüm)
Babel plugin, yalnız Text/View
v1.6.0
11 Temmuz 2026
Opt-in Image optimizer
v1.7.0 / v1.7.1
3 Eylül 2026
RN 0.86 desteği, Image optimizer varsayılan
v2.0.0
13 Eylül 2026
Metro config plugin mimarisi, 5 yeni optimizer, Uniwind
v2.0.1 / v2.0.2
14 / 18 Eylül 2026
Küçük düzeltmeler

27 Eylül 2026 itibarıyla depo 575 yıldıza, 2 açık issue'ya sahip ve son push 18 Eylül 2026'da gerçekleşmiş — aktif geliştirme sürüyor. Bugün paketi denemek istiyorsan yukarıdaki v2.x mimari değişikliğini dikkate alarak resmi dokümantasyondaki güncel kurulum adımlarını takip etmen gerekiyor; bu yazıdaki babel.config.js örneği v0.6.2 dönemine ait tarihsel bir referanstır.

Sonuç

React Native render performansı, tek bir sihirli anahtarla değil katman katman iyileşiyor: JS tarafında re-render disiplini, derleme zamanında gereksiz sarmalayıcıların azaltılması ve mimari seviyede JS-native iletişim hızı. react-native-boost, ikinci katmanda dar ama net bir iş yapıyor — statik analizle Text/View sarmalayıcılarını sadeleştirip derin listelerde ve grid'lerde ölçülebilir bir kazanç sağlamayı hedefliyor. Bu yaklaşımı React Native vs Flutter karşılaştırması yazımızdaki genel performans tartışmasıyla birlikte okumak, çapraz platform seçiminde render katmanının nereye oturduğunu netleştiriyor.

Benzer derleme-zamanı ve render-katmanı optimizasyonlarını platformlar arasında karşılaştırmak istersen Flutter performans optimizasyonu ve SwiftUI performans optimizasyonu yazılarına bakabilirsin; ikisi de aynı "ölç, sonra optimize et" disiplinini farklı render motorlarında ele alıyor. Çapraz platform performans disiplinini native tarafta da görmek için Rust ile mobilde paylaşımlı çekirdek (UniFFI) ve iOS performans izleme yazıları da faydalı referanslar.

Kısacası: react-native-boost'u üretime almadan önce mutlaka baseline ölç, Metro cache'ini temizle ve en pahalı ekranda opt-in test et — bu üç adım, "hızlandı" hissini ölçülebilir bir karara dönüştürüyor.

Kaynaklar

Etiketler

#react-native#render performansı#babel plugin#fabric#metro#profiling
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

12+ yıllık deneyime sahip Lead Mobile Engineer. Swift, SwiftUI, Kotlin ve Flutter ile iOS, Android ve cross-platform mimarilerde uzman. Performanslı ve kullanıcı dostu mobil uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

İlgili İçerik