[譯] 非死book:我們是如何構建第一個跨平臺的 React Native APP
英文原文(國內或許不能訪問): https://code.非死book.com/posts/1189117404435352/
早些時候,我們介紹過 iOS版的React Native . React Native帶來的是用web方式的React - 自聲明式的UI組件和快速的開發迭代來完成手機平臺的功能,然后為了保持速度、保真性、并達到原生的體驗。今天我們很高興發布 React Native的Anroid版本 .
在非死book我們已經應用React Native在發布的產品有超過一年的時間了。幾乎是整整一年之前,我們的團隊開始規劃開發 廣告管理APP 。我們的部門是創建一個新的APP來讓數百萬的非死book廣告主來管理他們的賬號并能創建新的廣告。在完成的時候,這不僅僅是FB的第一個全React Native APP而且是第一個跨平臺的APP.在這篇文章里,我們希望能和你分享我們是如何構建這個APP,React Native是如何讓我們更快的,還有這個過程中我們的經驗。
選擇React Native
不久前,React Native還是一項新的技術,還沒有被一款正式的產品應用過。并且開發這樣一個新的APP會有很大的挑戰,它超過了潛在的好處。
首先,我們初始的團隊里有三個產品工程師已經對React很熟悉。另外,這個APP需要處理大量復雜的商業邏輯和精確的處理不同的廣告格式、時區、日期格式、貨幣、匯率等等諸如此類。而大部分已經用JavaScript來實現了。全部用Objective-C編碼并稍后用java實現Android版本的想法也并沒有被贊成,而且也并不高效。第三,用React Native將會很容易來實現大部分的UI,可以實現帶數據的列表、表格、圖表。產品工程師可以很快的實現這些效果,用React就可以了。
當然,一些特性的實現存在著挑戰 - 比如,圖片的編輯,用來讓廣告主縮放和剪切圖片;地圖視圖,用來讓廣告主設定地理范圍。另外一個是面包屑導航,幫助廣告主來可視化的知道自己的層級位置。這些都提供機會讓我們來推動這個平臺的發展。
首先實現廣告工具的iOS版本
我們的團隊覺得首先開發iOS版本,也是為了和React Native的iOS版本校準一致。我們從后面的幾個月時間里從3個增加到8個工程師。新加入的成員對React并不熟悉 - 其中也并不熟悉JavsScript - 但是他們都渴望構建一個偉大的手機應用來服務廣告主,并且他們成長的非常快。
有經驗React Native的iOS工程師幫助我們實現一些他們并沒有在React Native中實現的特性,像提供訪問相冊。他們也幫助我們和其它FB已經存在的APP在使用的iOS庫做關聯,像認證、分析、崩潰報告、網絡和推送提醒。這讓我們的團隊可以關注在產品上。
除了上面提到的,我們可以使用以前就寫好的JavaScript類庫。像 Relay ,一個通過 GraphQL 來傳遞數據到React應用的FB框架.另外的一系列庫用來處理國際化和本地化,它能很聰明的實現時區和貨幣的調用。這些庫的加載是在一個JSON的配置文件里,包括APP用到的iOS的本地關聯文件,僅僅暴露很少的native代碼。這讓我們的庫幾乎不需要修改就能使用。
我們遇到的最大的挑戰就是導航。為了導航廣告主的廣告和活動,我們想使用面包屑導航條。指引廣告的創建流程,我們需要一個導向式的導航條。在最上面,非常重要的是需要使用合適的動畫和手勢操作,否則這個APP看起來還是像一個經過美化的website.
我們的解決方案是使用 導航組件 ,是一個用React Native來實現的可定制化的組件。本質上,它是一個追蹤一系列React組件的組件。它可以在組件之間基于按鈕點擊和按下時進行動畫切換。它也具有可插拔式的導航組件,讓我們來實現iOS風格的導航視圖,以面包屑的方式來導航廣告和活動,指引創建流程的步驟。這個導航條組件還能獲取到動畫的進度以及根據需要來調整動畫的頻率。這意味這所有動畫,包括視圖和導航條都可以通過JS來處理,而且測試的結果是仍然能夠達到60fps.
只有一種情況下動畫才會卡頓,就是當JS線程被一個大的操作占用時。當我們遇到這種情況時,基本上都是執行大量的數據獲取操作造成的。必然的,當導航到新頁面時需要加載大量的數據。當網絡足夠快是,動畫可以很容易的被執行。我們的解決方案是延遲數據的獲取直到動畫執行完畢,這時就使用到了 InteractionManager 組件,同樣是React Native的一部分。我們首先動畫到一個新的視圖,然后再用Relay來執行數據加載進程,這樣就能自動的讓需要的React組件實現自動渲染了。
開發Android版本
當iOS版本的廣告管理工具接近開發完成時,我們開始著手Android版本的APP.移植React Native的Android是最好的方式來完成這個工作。幸運的是,React Native團隊已經在上面做了很多的工作。自然的,我們想盡可能的復用更多的代碼,因為大部分的視圖都很相似。當然,也有一些地方需要做Android個性化處理來和iOS版本有所區別,比如,導航的元素或者是調用本地的UI元素像日期選擇、開關等等。
幸運的是,React Native包的黑名單特性和React的抽象結構幫助我們最大化的重用代碼來實現跨平臺的功能。在iOS版本里,我們打包的時候忽略所有后綴名為.android.js的文件。對Android的開發,忽略掉所有后綴名為.ios.js的文件。現在我們可以實現同樣的組件來同時應用Android和iOS,也可以個性化的編碼在不同平臺。替換掉 if/else 這種方式來判斷平臺,我們嘗試重構每個平臺的特定UI,這樣就可以有Android和iOS的不同實現。在構建Android版本的過程中,大約85%的代碼可以被復用。
另外一個挑戰是怎么管理源代碼的問題。Android和iOS的代碼庫在非死book兩個不同倉庫。廣告管理工具的iOS源代碼在iOS倉庫,Android版本的代碼在Android的代碼庫。舉例來說,像iOS版本的代碼,我們想用一些非死book的Android的依賴庫,這些庫卻在Android的代碼庫存放。另外,Android的APP所有的編譯工具,自動化,以及引入的其它插件都在Android的倉庫。基于上面,Android的這些app要求重構這些已經存在的iOS代碼來抽象具體平臺的組件來調用各自的文件。我們是可以直接合并兩個版本的代碼到一起。但是這種方式卻是我們不能接受的。
最后,我們決定指定iOS庫為事實上的源代碼庫,因為iOS版本已經相對穩定。我們設定了定時任務許多次一天來同步iOS的JavaScript到Android的代碼庫。我們不鼓勵在Android版本提交JavaScript代碼,如果提交也是在iOS版本同步的提交一份。如果同步代碼發現代碼有差異,會記錄一個任務用來進行后續的檢查。
我們讓iOS倉庫的JavaScropt打包成可以在Android版本上運行的代碼。這樣我們的產品開發人員就可以接觸到盡可能多的JavaScript代碼而沒有原生代碼,也可以直接在iOS倉庫直接修改和調試兩個版本的代碼。但是如果要構建Android的APP還是需要在Android倉庫來執行,同樣的操作也會在iOS APP - 測試兩個平臺的不同需要大量的額外工作。為了提高JavaScript開發者的工作流程,我們同樣構建了腳本來下載合適的來自整合服務器的原生文件。對于大部分開發者來說就不需要復制一份Android的代碼庫了 - 他們就可以在iOS代碼庫開發完整的JavaScript代碼,并且能比在非死book的web流程中更快速的進行迭代。
我們學到的
React Native團隊開發的進程和我們的APP一起,并且和他們一起調試本地化組件和API。這些組件將會為每個構建APP的人帶來幫助。盡管我們必須自己來構建一些組件,用React Native代替純原生的方式仍然是有價值的。我們不得不需要寫這些組件,雖然在未來的一段時間里也可能不會被其它團隊再次使用。
學到的另外一課是在分開的iOS和Android代碼倉庫工作是一件困難的事情,盡管使用了大量的工具和自動化。在構建APP的過程中,非死book用過這樣的模式,我們所有構建的自動化和開發進程都建立并圍繞著它。然而,對于產品來說,用一份共享的JavaScript代碼庫,這種方式并不好。幸運的是,非死book已經對所有平臺都 統一了代碼庫 - 只需要一份JavaScript的拷貝,同步那樣的方式已經成為了過去。
另外學到的是關于測試。當做了修改,每一個工程師一定要在所有平臺仔細測試,這個過程很容易出現人為的錯誤。但是開發一個跨平臺的APP而且是用一套代碼,這些是必須的。即便如此,由于測試不足導致的成本,遠大于用React Native開發的成本和能重用跨平臺代碼的成本。請記住,這里說的不僅僅是產品工程師;同樣包括React Native平臺的Objective-C和Java工程師.他們的工作不是限制在原生語言。同樣包括JavaScript - 舉例來說,組件API和部分分享部分的實現。ISO工程師一般來說不必一定要測試修改后的Android的代碼,對應Android工程師也是一樣。這種文化缺陷需要我們用時間和努力來消除,隨著時間的推移,我們會越來越穩定。
在每次修改整合版本的時候我們也會標記問題。這些標記的東東可以獲取iOS版本的問題,同樣的對Android也適用,我們連續的整合版本不會在iOS修改的時候來運行Android的測試,反過來也一樣。這樣工程師就可以更多精力來解決問題,并且不用經常的來重啟APP.
隨著上面說的和做的,我們的債算還完了 - 我們可以運行非死book的第一個完全的React Native APP在兩個平臺上,具有原生體驗,同樣的JavaeScript工程師團隊。他們當中有些還并不熟悉React, 但是他們在5個月之后就開發出了具有原生體驗的iOS版本,之后三個月,我們又發布了Android版本。
來自: https://segmentfault.com/a/1190000005091857