az év elején bemutattuk a React Native for iOS alkalmazást. A React Native a React on the web — deklaratív, önálló felhasználói felület komponensekből és gyors fejlesztési ciklusokból hozza a fejlesztőket a mobil platformra, miközben megőrzi a natív alkalmazások sebességét, hűségét és érzését. Ma örülünk, hogy kiadja a React Native for Android.
a Facebook-on már több mint egy éve használjuk a React Native-ot a termelésben. Majdnem pontosan egy évvel ezelőtt csapatunk elindult a Ads Manager alkalmazás fejlesztésére. Célunk egy új alkalmazás létrehozása volt, amely lehetővé teszi, hogy a Facebook-on hirdető emberek milliói kezeljék fiókjaikat, és útközben új hirdetéseket hozzanak létre. Végül nem csak a Facebook első teljesen reagáló natív alkalmazása volt, hanem az első platformközi alkalmazás is. Ebben a bejegyzésben szeretnénk megosztani veletek, hogyan építettük ezt az alkalmazást, Hogyan React Native lehetővé tette számunkra, hogy gyorsabban mozogjunk,valamint a tanulságokat.
A React Native
kiválasztása nem is olyan régen, a React Native még mindig egy új technológia volt, amelyet nem bizonyítottak a termelésben. Míg egy új alkalmazás kifejlesztése ezen a technológián alapul, némi kockázatot jelentett, ezt felülmúlta a lehetséges upsides.
először három termékmérnökből álló kezdeti csapatunk már ismerte a React – et. Másodszor, az alkalmazásnak sok összetett üzleti logikát kellett tartalmaznia a hirdetési formátumok, időzónák, dátumformátumok, pénznemek, pénznemek stb. Ennek nagy részét már JavaScript-ben írták. Az a lehetőség, hogy ezt a kódot csak az Objective-C-ben írjuk, hogy később Java-ban írjuk az alkalmazás Android verziójára, nem volt vonzó — és nem is lenne hatékony. Harmadszor, a React Native – ban könnyű lenne megvalósítani a legtöbb UI felületet, amelyet építeni akartunk-sok adat megjelenítése listák, táblázatok vagy grafikonok formájában. A termékmérnökök azonnal produktívak lehetnek ezen nézetek megvalósításában, mindaddig, amíg tudták, hogy reagálnak.
persze, bizonyos funkciók bemutatott kihívást jelent ez az új platform — például a kép szerkesztő, amely lehetővé teszi a hirdetők zoom termés egy fotót, majd a térkép nézet, amely lehetővé teszi a hirdetők cél az emberek bizonyos körön belül egy helyen. Egy másik példa a breadcrumb navigáció, amely segít a hirdetőknek a hirdetések hierarchiájának megjelenítésében a fiókjukban. Ezek lehetőséget adtak arra, hogy tovább nyomjuk a platformot.
Building Ads Manager for iOS first
csapatunk úgy döntött, hogy először fejleszti az alkalmazás iOS verzióját, amely nagyon jól illeszkedik a React Native-hoz, amelyet először az iOS számára fejlesztettek ki. A következő hónapokban háromról nyolc mérnökre növeltük a csapatot. Az újoncok nem ismeri Reagálni, — de nem ismeri a JavaScript — de, hogy alig várták, hogy építsenek egy nagy mobil élményt a hirdetők, ők tetszik gyorsan.
a React Native csapat tapasztalt iOS mérnökei segítettek áthidalni azokat a funkciókat, amelyek még nem voltak elérhetők a React Native alkalmazásban, például hozzáférést biztosít a telefon kameratekercséhez. Segítették az alkalmazás csomagolását a Facebook néhány meglévő iOS könyvtárával is, amelyeket már más Facebook-alkalmazásokban is használtak hitelesítés, elemzés, összeomlási jelentések, hálózatépítés és push értesítések elvégzésére. Ez lehetővé teszi, hogy csapatunk csak a termék felépítésére összpontosítson.
mint már említettük, sok már meglévő JavaScript könyvtárat tudtunk újra felhasználni. Az egyik ilyen könyvtár a Relay, a Facebook keretrendszere, amely adatokat szolgáltat a GraphQL-en keresztül reagáló alkalmazásokhoz. A könyvtárak egy másik csoportja a nemzetköziesítéssel és a lokalizációval foglalkozott, ami bonyolult lehet időzónák és valuták esetében. Általában ezek a könyvtárak betölteni a megfelelő konfigurációt egy JSON végpont a honlapon. Írtuk szkriptek exportálni a JSON fájlokat az összes támogatott helyszíneken, tartalmazza a fájlokat az alkalmazás segítségével iOS honosított kötegek, majd téve a JSON adatokat JavaScript néhány sor natív kódot. Ez lehetővé tette könyvtáraink szinte változatlan működését.
az egyik legnagyobb kihívás a navigációs áramlások voltak. Egy hirdető meglévő hirdetéseinek és kampányainak navigálásához egy breadcrumb navigációs sávot akartunk. A hirdetés létrehozásához szükségünk volt egy varázsló stílusú navigációs sávra. Ráadásul az is fontos volt, hogy az átmeneti animációk és az érintésmozdulatok is rendben legyenek, különben az alkalmazás inkább dicsőített mobil webhelynek érezte volna magát, mint egy natív alkalmazás.
megoldásunk a Navigator komponens volt, amelyet a React Native mellett elérhetővé tettünk a CustomComponents könyvtárban. Lényegében ez egy React komponens, amely nyomon követi egy sor más React komponensek egy verem. Ezen komponensek egyikét képes megjeleníteni, majd gombnyomások vagy érintési gesztusok alapján animálni közöttük. Ez is egy dugaszolható navigációs sáv komponens, amely lehetővé teszi számunkra, hogy végre egy iOS-szerű navigációs sáv a legtöbb rendszeres nézetek, zsemlemorzsa navigálás hirdetések és kampányok, valamint egy varázsló-szerű léptető a teremtés flow. A navigációs sáv komponens értesítést kap az animáció előrehaladásáról, és képes végrehajtani a megfelelő animációs növekményt. Ez azt jelenti, hogy az összes animációt, mind a nézetek, mind a navigációs sávok esetében, JavaScript-ben számítják ki, de a tesztek azt mutatták, hogy még mindig képesek voltunk 60 fps sebességgel végrehajtani őket.
csak egy módja van annak, hogy a navigációs animációk dadogjanak, ekkor blokkolták a JavaScript szálat egy nagy művelet során. Amikor találkoztunk ezzel a forgatókönyvvel, szinte kizárólag az újonnan beolvasott adatok nagy mennyiségének feldolgozása miatt történt. Természetesen van értelme, hogy amikor új nézetre navigál, több adatot kell betölteni és feldolgozni. Egy kellően gyors hálózaton ez a folyamat könnyen zavarhatja a még folyamatban lévő navigációs animációt. Megoldásunk itt az volt, hogy kifejezetten késleltessük az adatfeldolgozást az animációk befejezéséig, az InteractionManager komponens használatával,amely szintén a React Native részeként szállít. Először animálnánk egy olyan nézetet, amely helyőrzőket tartalmazott, majd hagyjuk, hogy a Relay elvégezze az adatfeldolgozást, ami automatikusan okozta a szükséges React komponensek újbóli megjelenítését.
Android verzió szállítása
amikor az iOS Hirdetéskezelője közel volt a szállításhoz,elkezdtük ugyanazon alkalmazás Android verziójának építését. A React natív port Android tűnt a legjobb módja annak, hogy ez a munka. Szerencsére a React natív csapata már keményen dolgozott, hogy csak ezt hozza létre. Természetesen azt akartuk, hogy újra annyi app kódot, mint lehetséges. Nem csak az üzleti logika, hanem a felhasználói felület kódja is, mert a legtöbb nézet nagyjából azonos volt, kivéve néhány stílust. Természetesen voltak olyan helyek, ahol az Android verziónak különböznie kellett az iOS verziótól, például a navigáció vagy a natív felhasználói felület elemek használata dátumválasztókhoz, kapcsolókhoz stb.
Szerencsére a Reagálnak Natív csomagoló tiltólista funkció Reagál az absztrakció mechanizmus sokat segített nekünk a maximalizálása kód újrafelhasználása át a két platformon, valamint minimálisra csökkenti a szükséges explicit platform ellenőrzi. Az iOS rendszeren azt mondtuk a csomagológépnek, hogy hagyja figyelmen kívül az összes fájlt .android.js. Az Android fejlesztés, figyelmen kívül hagyta az összes fájlt végződő .ios.js. Most végre ugyanazt az összetevőt egyszer Androidra, egyszer iOS-re, míg a fogyasztó kód feledékeny lenne a platformra. Tehát ahelyett, hogy explicit if/else ellenőrzéseket vezetnénk be a platformra, megpróbáltuk a felhasználói felület platformspecifikus részeit külön összetevőkké átalakítani, amelyek Android és iOS implementációval rendelkeznek. Abban az időben a szállítási Ads Manager for Android, ez a megközelítés így mintegy 85 százaléka újrafelhasználása app kód.
egy nagyobb kihívás, amellyel szembesültünk, a forráskód kezelése volt. Az Androidot és az iOS-es kódbázisokat a Facebook két különböző adattárában kezelte. Az iOS Ads Manager forráskódja természetesen az iOS tárolóban élt, míg az Android verzió kódjának különféle okokból az Android tárolóban kell élnie. Például, hasonlóan az iOS verzióhoz, néhány Facebook Android könyvtárat akartunk használni, amelyek az Android tárolóban éltek. Ezen kívül az androidos alkalmazások összes build eszközét, automatizálását és folyamatos integrációját az Android adattárhoz kapcsolták. Tekintettel arra, hogy az Android port az alkalmazás szükséges írd újra meglévő iOS kód absztrakt platform-specifikus komponensek a saját fájlok, mi volna, lényegében folyamatosan elágazás, majd egyesülő két változat azonos codebase. Ez számunkra elfogadhatatlan helyzetnek tűnt.
végül úgy döntöttünk, hogy az iOS tárolót az igazság forrásaként jelöljük meg, főleg azért, mert már ott volt, az alkalmazás iOS verziója volt a legérettebb. Létrehoztunk egy cronjob-ot, amely naponta többször szinkronizálta az összes JavaScript-kódot az iOS-ről az Android-tárolóra. A JavaScript futtatása az Android adattárban nem volt kedvét, csak akkor engedélyezett, ha azt követte egy kísérő kötelezettséget, hogy az iOS adattár. Ha a szinkronizáló szkript ellentmondást észlelt,további vizsgálatot indított.
azt is lehetővé tette, hogy a JavaScript packager szerver futtatni Android kódot az iOS adattár. Így a termékfejlesztőink, akik többnyire a JavaScriptet és a natív kódot érintették, fejleszthetik és tesztelhetik változásaikat mind az iOS, mind az Android rendszeren közvetlenül az iOS tárolóból. De ez még mindig megkövetelte tőlük, hogy az Android alkalmazás natív részeit az Android tárolóból építsék fel, ugyanez vonatkozik az iOS alkalmazásra is — hatalmas adó, amikor két platformon tesztelik a változásokat. Ahhoz, hogy gyorsítsák fel az áramlás csak a JavaScript fejlesztők, mi is épített egy script, amely letöltötte a megfelelő natív bináris mi folyamatos integrációs szerverek. Ez tette, hogy felesleges még egy klón a Android adattár a legtöbb fejlesztő — képesek a JavaScript fejlesztés, a forrása az igazság az iOS adattár, valamint halad olyan gyorsan, ahogy vagy gyorsabb, mint a Facebook webes verem.
amit megtanultunk
a React Native csapat kifejlesztette a platformot az alkalmazásunk mellett, és leleplezte azokat a natív összetevőket és API-kat, amelyekre szükségünk volt ahhoz, hogy ez megtörténjen. Ezek az összetevők mindenki számára hasznosak lesznek egy alkalmazás építésében a jövőben. Még akkor is, ha néhány komponenst magunknak kellett volna felépítenünk, a React Native használata tiszta natív felett még mindig megérte volna. Egyébként is meg kellett volna írnunk ezeket az alkatrészeket, és valószínűleg nem lettek volna újrafelhasználhatók más csapatok az úton.
az egyik tanulság az volt, hogy a különálló iOS és Android kódtárakban való munka nehézkes, még sok eszközzel és automatizálással is. Amikor az alkalmazást építettük, a Facebook ezt a modellt használta, és az összes build automatizálási és fejlesztői folyamatunk körülötte alakult ki. Ez azonban nem működik jól egy olyan termék esetében, amely nagyrészt egyetlen megosztott JavaScript-kódbázissal rendelkezik. Szerencsére a Facebook mindkét platformra egységes adattárba költözik — csak a közös JavaScript kód egy példányára lesz szükség, a szinkronizálás pedig a múlté lesz.
egy másik leckét tanultunk érintett tesztelés. A változtatások során minden mérnöknek ügyelnie kell arra, hogy mindkét platformon tesztelje, és a folyamat hajlamos az emberi hibákra. De ez csak egy elkerülhetetlen következménye a platformközi alkalmazás ugyanazon kódbázisból történő fejlesztésének. Ennek ellenére az elégtelen tesztelés miatt bekövetkező alkalmi balesetek költségeit messze felülmúlja a React Native használatával elért fejlesztési hatékonyság, és elsősorban a kód újrafelhasználása mindkét platformon. Ne feledje, hogy ez a lecke nem csak a termékmérnökökre vonatkozik, hanem az Objective-C-ben és a Java-ban dolgozó React natív platformmérnökökre is. Ezeknek a mérnököknek a munkája nagy része nem pusztán a megfelelő anyanyelvekre korlátozódik. Ez befolyásolhatja a JavaScriptet is-például komponens API-kat vagy részben megosztott implementációkat. A natív iOS mérnököket általában nem használják arra, hogy teszteljék a változásokat az androidon, a fordított pedig igaz az Android mérnökökre. Ez elsősorban egy kulturális szakadék, amely időbe és erőfeszítésbe került a Bezárás érdekében, és ennek eredményeként az idő múlásával stabilitásunk nőtt.
a problémát úgy is megoldottuk, hogy integrációs teszteket építettünk ki, amelyek minden felülvizsgálaton futnak. Bár ez dolgozott ki a doboz fogása iOS problémák iOS és hasonlóképpen az Android, a folyamatos integrációs rendszerek nem hoztak létre futtatni Android tesztek iOS revíziók és fordítva. Ez mérnöki erőfeszítést igényelt a megoldáshoz, és még mindig elég nagy hibahatár van ahhoz, hogy időnként megtörje az alkalmazást.
amikor minden elhangzott és megtörtént, a fogadásunk megtérült — két platformon tudtuk szállítani a Facebook első teljesen reagáló natív alkalmazását, natív megjelenéssel és érzéssel, amelyet ugyanaz a JavaScript mérnökök építettek. Nem minden mérnök ismerte a React – et, amikor csatlakozott a csapathoz, mégis építettek egy iOS alkalmazást natív megjelenéssel, mindössze öt hónap alatt. További három hónap elteltével kiadtuk az alkalmazás Android verzióját.
annak érdekében, hogy a nyelvünkben befogadóbb legyen, szerkesztettük ezt a bejegyzést, hogy helyettesítsük a fekete listát a blokklistával.