React Native Nedir? Nasıl Çalışır?

Mobil uygulama geliştirme ekibimizden Sait Banazılı, React kullanımı ile ilgili deneyimlerini Paynet Blog'da paylaştı.

Keyifli okumalar. Cross-platform mobil uygulama geliştirme macerası Angular ve Cordova üzerine kurulu Ionic gibi frameworkler ile başladı. Bu tür frameworklerin yaptığı şey temelde sizin Javascript + HTML + CSS ile geliştirdiğiniz client side uygulamalarınızı bir webview içerisinde çalıştırmak. Bu aslında o kadar basit bir mantık ki hali hazırda responsive bir mantıkla yazılmış bir websiteniz varsa, örneğin Android’de tek Activity ile bir proje oluşturup bir webview içinde sitenizi çalıştırsanız aşağı yukarı aynı şeyi elde edersiniz. Örnek olarak Ionic’in bunun üzerine kattığı tek şey Cordova aracılığı ile native API’lere erişim olanağı denebilir. (Kamera, sensörler, network, cihaz bilgisi vs.)

Bu frameworklerin en bariz dezavantajı: Performans!

Ve web teknolojileri ile sağlaması zor olan mobil hissiyatı

React Native nedir?

React Native, bir kullanıcı arayüzü geliştirme kütüphanesi olan React ile cross-platform uygulama geliştirdiğiniz bir framework. Ama burada asıl sihir React kelimesinde değil, Native kelimesinde. Bir React Native uygulaması HTML ile oluşturduğunuz bir hybird uygulama değil, webview içerisinde çalışmaz. React Native uygulamaları gerçekten native!

Peki nasıl?

React Native’i ilk araştırdığımda şöyle düşünmüştüm: React Native Javascript kodunu bir tür sihir ile parse ediyor ve bundan Java ve Objective-C kodu çıkarıyor. Sonuçta doğada bu tarz büyüler olduğunu biliyoruz. Compiler/transpiler dediğimiz şeyler aşağı yukarı bu tarz büyüler yapan şeyler. Ama hayır, React Native böyle bir şey yapmıyor.(bkz: Jasonette)

Ne yapıyor bu React Native?

Köprü yapıyor. Evet.

react native

ReactJS vs React Native

React Native, oluşturduğu native uygulama ile sizin yazdığınız JS uygulamasını köprü konsepti ile asynchronous ve çift yönlü olarak haberleştiriyor.

json view

UIManagerModule.java

Bu gördüğünüz bir React Native köprüsü. Hem de en önemli köprüsünün en önemli metodu. @ReactMethod bunun JS tarafına export edilecek bir metod olduğunu söylüyor.

Not: React Native köprüsünün temeli cross-platform çalışabilmesi için C++ ile yazılmıştır. Yukarıda gördüğümüz daha soyut bir seviye ama olayın özünü anlamak için yeterli. Meraklısı buraları inceleyebilir. React Native ile profesyonel düzeyde çalışsanız dahi C++ kodu yazmanız gerekmeyeceğini de belirteyim. Zaten çoğu zaman sadece JS kodu yazarsınız. Çok nadir durumlarda daha önce React Native köprüsü yapılmamış bir native SDK vs. bağlayacaksanız Java ve Obj-C/Swift ile kendiniz yapmanız gerekebilir.

Kaynak koddaki yolculuğumuza bir süre devam ettikten sonra şuraya geliyoruz:

nativview

NativeViewHierarchyManager.java

ViewManager

React Native bunu kullanmıyor. Ama kaynak kodun daha da derinlerine indiğimiz zaman benzer implementasyonları android.view.Viewandroid.view.ViewGroup gibi base class’ları kullanarak yaptığını görüyoruz.

Sonuç olarak;

React Native, ReactJS syntaxi ile yazdığınız JS kodundan köprüler aracılığı ile native view’lar oluşturuyor. JS kodunuz JS thread’de çalışırken native thread’e (UI thread) async istekler gönderiyor. Native taraf hazır olduğunda istenen native viewları native thread’de render ediyor, update ediyor vs. Yani meselenin özü haberleşme. React Native iki farklı dünyayı köprüler aracılığı ile haberleştiriyor. Fakat sonuçta elde ettiğiniz şey native thread’de çalışan native View’lar, ScrollView’lar, ImageView’lar vs. olduğu için native performansından çok bir şey kaybetmiyorsunuz ve uygulamanız gerçekten native olduğu için kullanıcılarınıza native mobil deneyimini sunabiliyorsunuz.

JSX

React ve React Native uygulamalarında arayüz JSX denilen bir syntax ile geliştirilir. Basit bir JSX kodu:

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

JSX sadece bir syntactic sugar’dır. React özelinde bir JSX tag’i aslında şu Javascript kodunun süslenmiş halidir.

React.createElement(component, props, …children)

Bu metod da kendi içerisinde Document.createElement() gibi DOM manipulasyon fonksiyonlarını kullanır.

Dolayısıyla soyut seviyede React Native için createElement()’in karşılığının bahsettiğimiz createView() metodu olduğu söylenebilir.

Flutter

Geçtiğimiz günlerde Google’ın geliştirdiği cross-platform mobil uygulama geliştirme frameworku Flutter stabil sürüme (1.0) yükseltildi ve adından çokça söz ettirmeye başladı.

Şahsen Flutter ile acemilik düzeyinde deneyimim oldu sadece. O yüzden React Native vs Flutter karşılaştırmasına çok girmeyeceğim. Ama kısaca söylemek gerekirse Flutter’ın zamana ihtiyacı olduğunu tahmin edebiliyorum.

React Native çok uzun süredir birçok önemli şirketin uygulamalarında ve belki milyon tane bağımsız mobil uygulamada kullanılmış bir teknoloji. Dolayısıyla ne kadar çok açık kaynak proje geliştirildiğini, kütüphaneler yazıldığını, StackOverflow’da ne kadar çok soru sorulduğunu vs. az çok tahmin edebilirsiniz.
 

Peki Flutter nasıl çalışıyor?

Flutter mimarisinin derinlerine inemeyeceğim. Fakat bildiklerimi kısaca özetleyeyim.

Flutter, Javascript’in aksine compiled bir dil olan Dart dilini kullanıyor. Dart hem JIT hem AOT derlenebilen bir dil. Bir Flutter uygulaması geliştirirken Dart JIT derleniyor. Bu da React Native’den aşina olduğumuz harika bir özellik olan Hot Reloading’i Flutter için de mümkün kılıyor. Fakat production aşamasında Dart AOT derleniyor ve bir takım büyüler yardımıyla Flutter Engine uygulamayı native tarafta render ediyor. Köprü yok, async kuyruklar yok. Bu da teoride React Native’in mevcut mimarisinden daha iyi performans vadediyor.

Fakat,

React Native’in çekirdek geliştirici ekibi bir mimari değişikliği üzerinde çalışıyor. Yeni mimaride yukarıda açıklamaya çalıştığım JSON ile gönderilen async render istekleri yok. Onun yerine native fonksiyonlar JSI ile doğrudan Javascript’e expose edilecek. Bunun bir diğer anlamı native taraf ile bellek paylaşımı olacak. Yukarıda bahsi geçen UIManager modülü ile alakalı kodlar bu yeni mimari ile çalışmaya başlayacak. Yeni mimaride serialization ve async kuyruklara ihtiyaç olmadığı için iletişim hızlanacak. Doğası gereği async olması gereken işlemler hariç scroll, animasyon gibi anında etkileşim beklediğimiz durumlarda React Native çok daha hızlı olacak.

https://youtu.be/UcqRXTriUVI

Flutter vs React Native

Sonuç olarak React Native’in yakın gelecekte performans konusunda önemli bir adım atıp Flutter ile burun buruna gidecek düzeye geleceğini öngörmek mümkün. Fakat elbette performans bu iki framework arasındaki tek tercih kriteri değil. Hatta günümüzde mobil cihazların işlem gücü düşünüldüğünde performansın giderek daha az önemli olduğu da söylenebilir.

Şahsen statik tipli compiled diller ile kod yazarken daha iyi hissediyorum. Bu biraz programlamayı başlangıçtan itibaren nasıl öğrendiğinizle de alakalı. Bu açıdan şimdiden Flutter’a uzaktan özenerek baktığımı itiraf etmem lazım.

Fakat tekrarlamak gerekirse Flutter’ın zamana ihtiyacı olduğunu düşünüyorum. Google’ın hem Dart dilini hem de Flutter’ı açık kaynak topluluğunun da desteği ile uzun bir süre geliştireceği aşikar. Bu arada açık kaynaklı ui projeleri geliştirilecek, birçok native SDK’in entegrasyonu yapılacak, insanlar acı çekecek, StackOverflow ve Github soru/cevaplar ile dolacak ve Flutter böylece profesyonel uygulamalarda gönül rahatlığı ile kullanılabilir olacak.

Şunu da söylemek lazım. React Native mobil uygulama geliştirme alanında büyük bir devrimdi. Ve başarılı bir devrimdi. Flutter, React Native’den ilham alan başka bir devrim. Başarısını hep birlikte göreceğiz. Arkasında Google gibi başta Android olmak üzere mobili ilgilendiren birçok teknolojinin geliştirilmesini üstlenen bir şirket olduğu için başarılı olacağından pek şüphe duymuyorum. Hepsini bir arada düşündüğümüzde cross-platform mobil uygulama geliştirme alanında muhteşem şeyler olduğu aşikar.