React: érik a horizontális ökoszisztéma
Villámgyorsan fejlődő, terebélyes fejlesztői platform lett a React, amelynek igazi potenciálját a mobilos kimenete, a React Native bonthatja ki. Ökoszisztémaépítés, élőben a nagyszínpadon.
Néhány hete az MWC-vel párhuzamosan zajlott a Facebook szokásos évi React.js Conf 2016 eseménye. Tavaly a cég elképesztően erős felhozatalt produkált, sorban jöttek a nagy bejelentések, mint a GraphQL, Relay, valamint a React Native. A Facebook hatalmas lendülettel vetette bele magát a fejlesztői ökoszisztéma építésébe, nem csoda, ha idén még fokozottabb elvárásokkal vártuk a bejelentéseket.
Ezért volt némileg meglepő, hogy az idei konferencia sokkal visszafogottabb lett, nem záporoztak az új kezdeményezések, és nem volt igazán nagyot durranó bejelentés. Mégsem nyújtott csalódást az esemény, de a meglepetést most inkább az adta, hogy a Facebook egy minden szempontból érett ökoszisztémát tárt elénk. Olyat, ami már minden jelentős platformot le tud fedni, és amelyet már külső fejlesztők tömegei használnak aktívan, sőt, tesznek is hozzá.
Érdemes visszatekinteni, hogyan jutottunk ide, és miért lehet ennyire magabiztos a Facebook. Nem történelemlecke lesz, és nem is az előadásokat szeretném összefoglalni, mint azt tettem a budapest.mobile csoportban. Inkább arról érdemes beszélni, hogy milyen tudatos és kitartó építő munkával jutott a cég oda, hogy az Apple és a Google platformjára saját fejlesztői keretrendszert húzzon, milyen problémákkal szembesült és milyen válaszokat adott ezekre.
Valós problémára valós választ
Sokan, sok fórumon felhozták már a Facebooknál tornyosuló mérnöki kihívások listáját, ezek közül csak említés szintjén menjünk végig néhányon. A sort a túl nagyra növő, túlterhelt, és ennek következtében nagyon lassú DOM működés kezdi, majd ezt tetézi a bonyolult, kiszámíthatatlan UI-logika, amihez a fejlesztés előrehaladtával egyre kevésbé mernek hozzányúlni a fejlesztők.
Ehhez vegyük hozzá, hogy a Facebook alapból több különböző platformot támogat, ezek kódbázisa töredezett, fragmentált, ami megnehezíti az új képességek egyidejű fejlesztését és a karbantartást. És persze a különböző platformokhoz különböző nyelvek és különböző keretrendszerek tartoznak, eltérő funkciókkal és lehetőségekkel. Ezek eredőjeként hatalmas méretű kódbázis jön létre, amit egy változatos, szerteágazó eszköztár szolgál ki, hiszen mindenik platformhoz más fejlesztői környezet, más build-rendszer és más CI (continuous integration) megoldás tartozik. Amitől igazán érdekes a történet, hogy ez egy jellemző helyzet, nagyon sok fejlesztőcégnél küzdenek hasonló problémákkal.
Így indult a történet...
A Facebook egyébként pont olyan alkalmazásokat épít, mint minden más mobilfejlesztő. Tipikus appok, View-val, Modellel, amelyek oda-vissza kommunikáltak egymással. Ahogy növekedett a kódbázis és egyre több képességet adtak az apphoz, úgy vált a kódbázis egyre nagyobbá, bonyolultabbá, és nehezen karbantarthatóvá.
Sokan sokféleképp mesélik, de a lényeg, hogy számos facebookos fejlesztőcsapatnál nagyjából egyszerre érte el a kritikus szintet a fent körülírt problémahalmaz. A legtöbb akadályba a Facebook hirdetésekkel és a csevegővel foglalkozó csapatai ütköztek, az előbbi, a hirdetéses brigád fektette le a megoldás alapjait is.
A probléma akkor kezdte igazán szúrni a menedzsment szemét, amikor fokozatosan lassult új feature-ök implementálása, egyre kiszámíthatatlanabb lett a kód viselkedése, majd egyszer csak eljutottak oda, amikor a fejlesztők mind kevésbé akartak bizonyos részekhez nyúlni, féltek, hogy valami rájuk omlik. Konkrétan elveszett a bizalom a saját kóddal szemben.
A megoldáshoz nagyjából 10-15 évvel korábbra nyúltak vissza. Az AJAX elterjedése előtti időkről van szó, amikor még az oldalon történő minden állapot változás esetében a teljes HTML-t a szervertől kértük le, amely újragenerálta az oldalt és elküldte a kliensnek, mely a megkapott új oldalt újratöltötte, lerenderelte, és az akkor szokásos sebességgel kirajzolta a képernyőre. Az AJAX kidobása még nem az út vége volt, a fejlesztők még tovább mentek, a felületet kisebb egységekre, úgynevezett komponensekre bontották, majd azokon belül is különböző állapotokat definiáltak.
Az így lecsupaszított prototípus nyilván elsőre nagyon lassú volt, de innen kiindulva, sok munka után jutottak el Virtual DOM-ig. Azért erőltették ezt, mert minden kezdeti betegsége ellenére a fejlesztőik szerették ezt a koncepciót. Ezen a ponton érdemes megállni, és megismerkedni ezzel a megközelítéssel, amely alapvetően a fenti probléma megoldását is magában hordozza.
Nagyon röviden összefoglalva, a Virtual DOM nem mást csinál, mint új rétegként beékelődik a kódunk és a DOM közé (vagy egy natív vezérlő hierarchia mögé), csokrokba gyűjti a DOM-on végzett műveleteket, és optimálisabban batchenként hajtva végre azokat, a változásokra figyelve. Ezek az ötletek, és a Virtual DOM volt az technológia, ami a React.js alapját jelentették.
Az MVC architektúra is a probléma része
A Virtual DOM bevezetésével párhuzamosan a fejlesztők leváltották az MVC architektúrát is. Az általánosan, széles körben használt MVC-vel akkor jelentkeznek a problémák, amikor számos View és számos Model található az alkalmazásban. Ha ezek egymással két irányú kommunikációt folytatnak, illetve mindegyik több másikkal is kapcsolatban áll, akkor láthatatlanul is visszacsatolásos hurkok alakulhatnak ki, amelyek nagyon bonyolulttá teszik az architektúra használatát bizonyos komplexitási szint felett.
Kiváló példa erre problémára a Facebook korábban sokat szidott chat és értesítések káosza. Sok kis, különálló alrendszer dolgozik itt össze, úgy a kis chat nézetek, amelyek alulról ugrálnak fel, a fejlécben jobb oldalt az értesítések, illetve a teljes képernyős chat nézet. Hatalmas kihívás ezek szinkronban tartása, és mivel ezekre a gondokra sokan emlékszünk, látványosan sokáig tartott úrrá lenniük ezeken a problémákon. Mondani sem kell, ez a felhasználói élményt rombolja, ami a legrosszabb, ami egy app esetében történhet.
A poszt-MVC-megoldás szintén a régi időkbe nyúlt vissza, ami megszüntette a nehezen átlátható és kezelhető két irányú kapcsolatokat. Helyette drákói szigorral visszavezette az AJAX előtti világban szokásos egyirányú adatfolyamot, vagy eredeti nevén unidirectional data flow-t. Az ábrán jól látható, ahogy a kommunikáció kizárólag egyetlen irányba folyik, felhasználói vagy külső interakció nélkül pedig egyáltalán nincs visszacsatolásos körfolyamat, a Store és a View között nincs oda-vissza üzengetés.
Az egyszerűség és átláthatóság azt is jelenti, hogy sokkal könnyebb ebben az architektúrában azonosítani és elhárítani a programozási hibákat. Ezt a struktúrát a Facebooknál Fluxnak nevezik, az egyik legnépszerűbb implementációja pedig a Dan Abramov-féle Redux. Nem véletlen egyébként, hogy a szakember egy ideje már a Facebook sorait erősíti.
Terjesszük ki a mobil fejlesztés irányába!
Első lépésként a weben vezette be a fenti irányt a Facebook, ebben a környezetben rendkívül jól működött, amit az bizonyít leginkább, hogy a facebook.com oldalon konkrétan a React.js-t használja a cég. A továbbgondolás sem váratott magára, jött az igény, hogy jó lenne az itt felépített tudást és megoldásokat átültetni mobilos környezetbe is. Voltak erre tett kísérletek, például az iOS-re megjelent ComponentKit. Bár a Facebook ezt használja, ezzel építi fel a falat, de nem terjedt el különösebben, és a cég sem érezte ezt végleges megoldásnak.
Visszatérve a mobilappok megreformálására: a natív alkalmazások mindkét nagy mobilos platformon saját kis világot jelentenek. És ez nem csak az eltérő UI-paradigmákra igaz, hanem ahogy már említettük a nyelvre, fejlesztői eszközökre, a felhasznált keretrendszerekre - ez a két nagy platform esetében rengeteg duplikált munkát jelent, mind a kód, mind az infrastruktúra szempontjából.
A Facebook a kezdetektől igyekezett ez alól kibújni, előbb a HTML5-ös irányt erőltette a cég (amikor a technológia még gyermekcipőben járt), majd annak bukása után egy rövid natív-natív periódust követően újra nekifutottak a fejlesztők az egységes mobilappnak. A Facebook tehát nem adta fel az álmot, annak ellenére, hogy az HTML5-ös megoldással megégette magát - a technológia akkor egyszerűen képtelen volt megfelelő felhasználói élményt biztosítani.
Az újrakezdéshez az igazi áttörést az hozta el, hogy az Apple kiadta a JavaScriptCore API-szettet iOS-re. Aminek a mi szempontunkból legfontosabb tulajdonsága, hogy az Objective-C és a JavaScript kód oda-vissza hívhatják egymást, így a rendszer erőforrásaihoz hirtelen hozzá tudnak férni a JavaScriptben írt alkalmazáskomponensek is.
Pontosan ez a lelke a React Native-nak, amely így nem egy Cordova-szerű hibrid webes alkalmazást, hanem egy natívan működő, de webes technológiákra épülő appot tud létrehozni. A React Native által használt Virtual DOM mögött teljesen natív UI vezérlők hierarchiája húzódik meg, natív kóddal kommunikál, így összességében natív élményt is ad. Mindezt úgy, hogy a natív vezérlőktől eltekintve még mindig a jól megszokott, webes Reactot használják a fejlesztők, de immár nem webes környezetben.
A JavaScriptCorenak köszönhetően lehetőség van arra is, hogy az alkalmazásnak csak egy része készüljön ezen a módon. Nem kell rögtön teljesen átállni, lehet kicsiben tesztelni, és haladni tovább, ha beválik. Így a meglévő alkalmazások is fokozatosan migrálhatóak Reactre, a sebességet a fejlesztők tetszőlegesen választhatják meg.
Így tesz egyébként a Facebook is, a saját fő alkalmazásán belül a csoportok (Groups) kezelése már reactos implementációt kapott, valamint rövidesen az események is ilyen formában alakulnak át. A dedikált alkalmazások, mint a Groups és az Ads Manager azonban már teljes egészében Reactban készült,
Az igazi varázslat (és a React Native) komoly megkülönböztető előnye, hogy a webes fejlesztés agilitása nem veszett el. Megvan a "live reload" élmény, vagyis írod a kódot, mented, és néhány másodperc múlva frissül is az eredmény az emulátorban, vagy akár a készüléken. Ez azt jelenti, hogy rendkívül gyorsan lehet haladni a felületek és a logika összerakásával,
A megközelítés egy járulékos előnye, hogy részben megkerülhető vele az App Store. Az iOS-es alkalmazásbolt mindenki nagy mumusa, az elkészült frissítések jóváhagyási-átfutási ideje 7-10 nap, ami nagyon sok - főleg akkor, ha az éles verzióban lévő bugot szeretnénk épp orvosolni. A Microsoft-féle Code Push, vagy az Exponent.js használatával azonban néhány egyszerű lépésben frissíthetőek lesznek az alkalmazások, anélkül, hogy bármelyik félnek is a Storehoz kellene fordulnia. És igen, ezt már az Apple is engedi.
Annyit még mindenképp érdemes megjegyezni, hogy rettentő fiatal, alig egy éves technológiáról van szó, sőt az Android verzió csak néhány hónapos. Habár nagyon gyorsan haladnak a készítők, de bele lehet futni gyerekbetegségek bőséggel. Aki belekezd, mindenképp számoljon azzal, hogy rögös lehet az út eleje.
JavaScriptből várat építeni?
A webes és a mobilappos React tehát közös API-t kínál, de nem csak ez, hanem a nyelv is közös, JavaScript formájában. Persze a Facebooknál is pontosan látják, hogy a "régi" JavaScript, az ES5 nem igazán alkalmas a feladatra, az ES6 (ES2015) azonban még mindig gyerekcipőben jár, támogatása nem széleskörű. És itt jön a huszárvágás: mi lenne, ha mégis használható lenne?
A megoldás a Babel, ami egy JavaScript fordító, és lehetővé teszi a következő generációs JS-képességek használatát már ma is. A fejlesztő tehát már írhat az új szabványoknak megfelelő kódot, amit a Babel olyan régi JS-re fordít, amelyet a böngészők illetve a már említett JavaScriptCore probléma nélkül tud futtatni. Nem véletlen, hogy a Babel fejlesztője, Sebastian McKenzie is a Facebooknál dolgozik már, egy egész csapatot kapott a fordító tökéletesítésére.
A React és React Native mellé tehát egy modern nyelvet is ad a Facebook a fejlesztők kezébe, az extra lépés, a Babel integrálása és a source mapek használata különösebb problémát nem jelent a gyakorlatban. Az eredmény kevesebb csapda és buktató, komolyan növelve a produktivitást.
A nyelvnél maradva: a JavaScript dinamikusan típusos jellege a komplex, nagy méretű appoknál már komoly hátrányt jelent. Sok problémára csak futás közben, rengeteg hibakereséssel, tesztek írásával lehet rájönni - ez ugyan ajánlott az erősen típusos nyelvek esetében is, a dinamikus típusoknál ezek abszolút elengedhetetlenek.
Ezeken segíthet a Flow, ami egy statikus ES6 típus ellenőrző. A kód típusinformációkkal ruházható fel, amelyek betartását ez a pici, a build folyamatba illeszthető tool ellenőriz, mely jelzi a potenciális és tényleges hibákat. Fontos, hogy opt-outolható, a fejlesztő dönthet úgy, hogy kikerüli, ugyanakkor ez váratlan hibák forrásává válhat.
Horizontális platform
Gondoljuk tehát végig: a Reacttal egységesen célozható meg web, iOS és Android is. Nyilván az egyes platformok különböznek, külön-külön kell a felületeket minden platformhoz leprogramozni, de az üzleti logika működhet közös kódbázissal, redundáns fejlesztések nélkül. Ezt a metaplatformot nevezi a Facebook újabban horizontális platformnak, amely képes elfedni a fejlesztő felé a különböző rendszerek egyedi jellemzőit, különbségeit.
A platform tehát szép lassan összeáll, van hozzá nyelv, és egy-két fejlesztői eszköz is. Ez a terület, ahol a Facebook igazán támadásba lendül, a fejlesztői eszköztár egységesítése és közös nevezőre hozása. Ennek egyik eleme a Buck: egy gyors build rendszer, ami React Native alkalmazások esetén is használható. A webes React esetében pedig ott van számos, a webről megismert build tool, mint a Webpack, a Grunt, vagy épp a Gulp. Kis szépséghiba, hogy ezt a két világot még nem vonta össze a Facebook, tehát maradt bejelenteni való jövőre is.
Egységesítették IDE-t is, a Nuclide egy Atom-bővítmény, ami nagyon felgyorsult az utóbbi időkben, és tanult is számos trükköt. Viszont lehet mást is választani. Ha valaki Continuous Integration, vagy béta disztribúciós rendszert keres, mindkettőre kínál már jó megoldásokat többek közt a Microsoft is.
Mi történt az idei konferencián?
És a rövidnek nem nevezhető történelmi kitérő után meg is érkeztünk a jelenbe. A konferenciát megelőzően nem sok tippem volt mire számíthatok, a keynote alatt viszont gyorsan világossá vált az üzenet, a két nap végére pedig megértettem, hogy minden oka megvolt a Facebook csapatának a magabiztosságra. Lássuk távirati stílusban a bejelentéseket!
React Dev Tools Chrome plugint már több mint 225 ezer ember töltötte a 2013-as indulás óta, aprótól az óriás média- és sportcégekig rengetegen használják a Reactot a rendszereik építéséhez. Ráadásul valóban hatalmas közösség gyűlt össze mögötte, akik együtt egy igazi ökoszisztémává emelik a megoldást, ami messze túlmutat már a Facebook erőfeszítésén. A közösség erejét a Facebook is elismeri, a cég bejelentette, hogy megnyitja a Facebook Notes szövegszerkesztőjének forráskódját, ez lesz a Draft.js. A már említett Nuclide eddig is kezelte a React.js-t, de már készül a React Native Tool csomag, ami nagyon ütősnek ígérkezik.
A kezdeményezést a Microsoft is minden oldalról igyekszik támogatni, rengeteg jó dologgal állt most elő, a cég a Cordova mellett egyaránt kiemelten támogatja a React Nativeot is. A Visual Studio Codehoz új bővítmény készül, immár React támogatással, a Code Pusht pedig már említésre került korábban. A Visual Studio Team System a Continuous Integrationt nyújtja. A Hockey App pedig a béta appok disztribúciót teszi jelentősen egyszerűbbé.
Ünnepi mix a bértranszparenciától a kódoló vezetőkig Négy IT karrierrel kapcsolatos, érdekes témát csomagoltunk a karácsonyfa alá.
A Vivek Patel a Googletől email template toolokat mutatott be Reacttal. Az Exponent.js a Microsoft Code Pushéhoz hasonló csomag, amivel távolról, Store review nélkül lehet a kódot frissíteni. A Falcor a Netflix saját data fetching könyvtára, ami egy GraphQL alternatíva. Az Airbnb féle Enzym a tesztelést teszi könnyebbé, jQuery szerű API-vel a DOM bejárást és manipulációt. De itt van a Realm, a gl-react, támogatják a VR-t is, komolyan mondom felsorolni is nehéz, annyi minden van.
Nagy meglepetést és sok kérdő tekintetet váltott ki, hogy a 0.14 után 15.0-ra ugranak a verziók számozásában. Nem csak az 1.0-t, hanem az összes közbeeső számot kihagyják. De végső soron ez is egy verziózás, és abszolút kifejezi, hogy itt nagyon is egy érett megoldásról van szó, amit bátran lehet élesben, productionben használni.
Még egy gondolat
Továbbra is nagyon meggyőző, amit a Facebook csapata, és a köréjük rendeződött közösség épít. Nincs afelől semmi kétségem, hogy idén az Angular 2-vel egyetemben komolyan meg fogják határozni a kliensoldali fejlesztések képét. Végül a témában még egy posztot szeretnék a figyelmetekbe ajánlani, itt gyűjtöttem össze az információkat azoknak, akik szeretnének megismerkedni a React Native-val.
A cikk szerzője Orosz Gábor, a Budapest Mobile fejlesztői Facebook-csoport alapítója, szabadúszó fejlesztő.