React Native Performans İpuçları — 1

Çağatay Yıldız
BilgeAdam Teknoloji
6 min readJan 10, 2022

Hybrid ve benzeri programlama yöntemleriyle mobil uygulama geliştirmek başta çok cazip gelse de süreç içerisinde kimi performans sıkıntılarıyla karşılaşıyoruz. Paketler arasındaki uyumsuzluk, cihazlar arasında ( bazen android, bazen ios ) tutarsızlıklar geliştirme sırasında ciddi maliyetlere yol açıyor. Uzun yıllardır hybrid mobil uygulama geliştiren ve son dönemde React Native platformunda mobil uygulama geliştiren biri olarak yaşadığım performans sıkıntılarını ve bir nebze de olsa çözümlerini paylaşmak istedim.

Başlamadan önce merak edenler React Native resmi dökümanına bakabilir. Arkadaşlar performans sıkıntılarına yönelik bir şeyler paylaşmışlar.

1. State Yönetimi ve Hooklar

React platformunda kod yazmaya başladığımızda hızlı geliştirme imkanı veren state mantığı proje büyüdükçe bize çelme takabiliyor. Parent — Child componentler arasındaki ilişki karmaşıklaştıkça bu componentler birbirini anlamsız bir şekilde render edebiliyor. Ortak state kullanan kimi componentler ( context vb. yollar aracılığıyla ) anlamsız performans sıkıntılarına yol açabiliyor.

UseMemo, React.Memo ve UseCallback

React developerları bu gibi sorunlar için pratik bazı hooklar ve metotlar tanımlamışlar. Bu sayede componenti hafızada tutup bazı render işlemlerinden koruyabiliyoruz.

  • Bir componenti React.Memo ile sarmalladığınız takdirde componente bağımlı bir state değişmediği sürece componenti render etmiyoruz. Böylelikle parent bağımlılığından kurtarıyoruz. Component’in toplam render maliyeti yüksek ise tercih edilmesi gereken bir yöntem.
  • Component içerisinde maliyetli bir metodumuz var. Sadece bu metodu UseMemo ile sarmallayıp belli bir state e bağlayabiliriz. Yani componentin kendisi render olsa dahi metodumuz çalışmayacak ve bize avantaj sağlayacaktır.
  • UseCallback React ın ilginç hooklarından bir tanesi. UseCallback ile sarmalldığınız metodun işlevini saklıyorsunuz. Böylelikle render sonrası referans karşılaştırması yapmayan React metodunuzun işlevini rahatça saklayabiliyor.

2. Gizli Baş Belası — View

React Native deki View yapısı kabaca Html deki div yapısına karşılık geliyor. Birçok developer mevcut yapılarını defalarca View le sarmallayor. Her View native code dönüşümünde IOS ve Android platformunun kendi View lerine dönüşüyor. Başta bir sorun teşkil etmese de “deep trees” dediğimiz yani iç içe View yapılarında hem performansta hem de development aşamasında başımıza bela oluyor. Özellikle oluşan View lerin boyanması ( yani backgroundColor verilmesi ) üst üste boyamalarda sıkıntı yaşatıyor.

React 16 dan itibaren bu yapı yerine Fragment olarak belirttiği boş düğüm yapılarını geliştiricilere önerdi.

React-devtools paketini kullanarak mobil uygulamamızdaki ağaç yapısını görmemiz mümkün. Native olarak gerek android gerek ios platformunda bunu görmemiz ciddi bir avantaj. Özellikle tavsiye ettiğim bir paket. “Usage with React Native” bölümünden paketin kullanımına bakabilirsiniz.

3. StyleSheet Kullanımı

Inline yazdığımı style lar her render sonrası tekrar hesaplanıyor. Böylelikle her seferinde yeni bir style tanımış oluyoruz. React Native bunun yerine StyleSheet kullanmamızı öneriyor. Böylelikle bir kere referansı oluşan style bloğunu render sonrası bize bir avantaj sağlıyor. ( Özellikle hızlı render olması gereken listelerde bu performans gözlemlenebilir. Bunun dışında gözle görünür bir etki yok. )

Aynı zamandaStyleSheet kullanarak daha okunaklı kod yazmamız da mümkün.

Not olarak web geliştirme ortamında yoğun ve tekrar stlye işlemi barındıran durumlarda aşağıdaki paketi kullanmamız mümkün. Paketi ve performansı konusunda detaylı bir yazıyı paylaşıyorum.

4. Bitmek Bilmeyen Listelerimiz — SectionList, FlatList ve Diğer Kahramanlar

Yakın zamanda scroll sırasındaki performansın krtik bir uygulamada geliştirme yaptım. Bu esnada çok fazla paketi deneme fırsatım oldu. Düşük listeler için FlatList, SectionList gibi paketler oldukça yeterli. Paketleri konfigürasyonunda yapacağınız ufak müdahelelerle istediğiniz performansı elde etmeniz mümkün. Fakat bitmek bilmeyen ve kompleks view ler barındıran durumlarda React Native in bu iki paketi sınıfta kalıyor. Mobil cihazın boyama sırasında yaşadığı sıkıntıyla birlikte ekranda yoğun beyazlıkları görmeniz ve listenin sizi sonradan takip etmesi büyük olasılık.

Flatlist performansı için bir makaleyi aşağıda bırakıyorum. İnternette birçok kaynakta da FlatList performansı için benzer maddeleri görmek mümkün. Benim gözüme çarpan ortak maddeler ve kaynaklar şu şekilde:

  • Arrow Function kullanımı
  • UseCallBack kullanımı
  • KeyExtractor propunun belirlenmesi
  • maxToRenderPerBatch propu ile render edilecek sayının önceden belirlenmesi
  • Liste içerisindeki image lerin yönetimi ( boyut yönetimi )
  • window size ile boş alan ve bellek yönetimi

BigList — RecyclerListView

Aşağıda bulunan iki paket büyük listelemelerde çok iyi bir performans gösteriyor. İki paketi de kullanma şansım oldu. Önerim RecyclerListView paketi fakat kullanmadan önce github issue larına bakmakta fayda var. Paketlerdeki scroll position gibi benzer sıkıntılar canınızı sıkabilir.

5. Boyama İşlemleri — BackgroundColor — Button — BorderRadius

Webden boyama işlemleri olarak aklımızda kalan ( Browser Painting ) işlemleri yukarıdaki gibi uzun listeli işlemlerde tekrar karşımıza çıkıyor. “Css painting time” anahtarındaki birçok özellik burada da geçerli. Color tanımlamalarında mümkünse renk adı değilse hex color code kullanılması, yine uzun listelerde button gibi maliyetli componentler yerine mümkünse Text kullanılması ve elbette yine mümkünse borderRadius gibi hesaplamalardan kaçınılması oldukça önemli.

( Bu madde görece kötü android cihazlarda ve uzun listelerde gözle görülür bir performans etkisi gösterecektir. )

6. Dışı Seni İçi Beni Yakar — Animation

Sanal makinalarımızda veya iyi cihazlarımızda test ettiğimiz bir çok animasyon canlı ortamlarda ciddi performans kayıplarına yol açmakta. Biraz internet aramasında “JS thread is too busy” cümlesiyle karşılaşmanız mümkün. Single Thread boyama yapısı kimi durumlarda işleri ciddi ölçüde kitliyor. Her ne kadar alternatif çözüm üretilse de — Javascriptin doğası gereği — işimizi zorlaştıran maddelerden biri.

Interaction Manager

React Native in kendi özelliği olan Interaction Manager ile animasyonlarımızın çalışma zamanını yönetmek mümkün. Böylece animasyonun ne zaman hangi durumda çalıştığını yöneterek bazı sıkıntılardan kurtulabiliriz.

Ayrıca animasyon işle performans açısından React Native Gesture Handler kullanmamız oldukça önemli. Zaten bir nebze animasyon işine bulaştığınızda bu paket sizin karşınıza çıkacaktır :)

React Native thread yapısının hangi durumlarda başa bela olacağı ve genel yapısını aşağıdaki yazıda öğrenmeniz mümkün.

7. Arkamızdan Gelen Componentler — React.Lazy

“Lazy loading” anahtar kelimesinin yazılımcılar için anlamı olduğunu bilen React developerları Lazy adında kullanışlı bir yapı üretmiş. UI thread kitlenmelerini engellemede oldukça işe yarayan bu yapı sayesinde Belirttiğimiz componentler arka tarafta yükleniyor ve biz işleme devam edebiliyoruz. Gerek Reactjs gerek React Native tarafında kullanmamız mümkün.

8. Kıyıda Köşede Kalan Console.Log lar

React Native vb. platformlarda geliştirme yapmanın can sıkıcı taraflarından biri de projenizin bir süre sonra console.Log satırlarıyla dolması. Yayına aldığınızda bu console blokları başınıza bela olabilir. Özellikle belirli bir timingde veya döngüde çalışan bloklar performansınızı etkileyebilir.

Bu konuda React Native resmi dökümanında aşağıdaki paketi tavsiye ediyor.

JS Hermes motorunun kullanılması, resim optimizasyonları, workerler vb. konuları yazının ikinci bölümüne sakladım. Şimdilik bu kadar.

Sevgiyle :)

Diğer Kaynaklar

--

--