Udacity 移動端團隊最近刪除了 App 中使用 React Native 語言開發的相關功能。css
咱們收到大量有關咱們用法或 React Native 的問題以及爲何咱們中止投入資源和精力在 RN 上。java
在這篇文章中,我但願可以回答咱們收到的大多數問題並深刻了解:ios
我固然不會聲稱本身是 React Native 的專家。咱們團隊中的其餘人比我有更有經驗,但我相信他們也不會自稱專家。git
我將根據咱們本身的經驗談論在咱們的特定狀況下作什麼和不作什麼。至於 React Native 是否適合你的團隊/項目取決於你,但但願這篇文章可以提供額外有用的數據點供你參考。程序員
「React Native 是否適合你的團隊/項目取決於你」web
我仍是想指出,這些經驗和意見來自 Udacity 的移動工程團隊,而不是其餘任何人。這裏的想法並不反映任何其餘團隊使用或構建 React 或 React Native 內容的意見。面試
首先要搞清楚的事情。咱們的團隊是什麼樣的?團隊規模,經驗和所在組織有能力將 React Native 的可行性在項目中產生實際影響。npm
咱們的移動端團隊分佈在 iOS 和 Android 平臺上。swift
團隊規模api
最初引入 React Native 時:
到了今天:
在咱們使用 React Native 長達 18 個月的過程當中,咱們的iOS 和 Android 團隊的規模都在保持增加。
團隊更由一位新的產品經理負責。
咱們經過多名設計師和設計範例進行過轉型。
開發背景
引入 React Native 時,使用 Javascript 和 React 範例的每一個團隊有多溫馨?
iOS
iOS 團隊的惟一開發人員以前擁有豐富的 Javascript 和 Web 開發經驗,很是樂意使用 React Native 開發。
現在,四個 iOS 開發者中至少有三個習慣並適應使用 Javascript 和 React Native 技術。
Android
在引入 React Native 時,兩位 Android 開發人員中有一位對 Javascript 感到滿意。另外一位(也就是我本身)只有不多的Javascript,React 或 web 開發背景。
後來加入團隊的其餘 Android 開發人員也幾乎沒有 Javascript 或 Web 經驗。
咱們的產品是作什麼的?
咱們的手機應用旨在爲將 Udacity 學習體驗帶到你的手機設備上。它們支持身份驗證,內容發現,程序註冊(在某些狀況下還有支付),最後支持各類程序和內容類型的學習材料的消費。
這些應用也是新的實驗性功能和計劃的試驗場所,目的在於改善用戶的總體學習效果。
代碼庫規模
同等
引入 React Native 後,應用程序的功能也很是接近。
隨着時間的推移,核心體驗大體至關,但每一個團隊都增長有或多或少的對另外一個平臺的經驗。
此外,因爲國際需求的擴大,本地化和更小的 apk size 等成爲 Android 團隊愈來愈重視的事情。Android 團隊還與其餘地區的團隊密切合做,針對非 iOS 須要考慮的市場特定功能。
咱們爲何要引入?
咱們開始推出全新的移動端專有功能。咱們但願在兩個平臺上快速進行實驗和驗證,所以跨平臺開發很是具有吸引力。
由於它是一個新的而且獨立的功能,因此被認爲是嘗試跨平臺開發的契機。
選擇 React Native 有幾個緣由:
咱們是如何引入的?
最初的 React Native 功能是在一個單獨的 GitHub 倉庫中構建的,並做爲 git 子分支分別併入 iOS 和 Android 倉庫。
這樣能夠實現很是快速的原型設計,而且若是須要,能夠將該功能做爲獨立產品發佈。
更多的經驗是原型,最終咱們在 React Native 代碼庫中引入了第二個更大的功能。
時間線
答案直截了當。
咱們從應用程序中刪除最後的 React Native 代碼,由於惟一剩下的 React Native 開發的功能已經下線,咱們再也不須要支持。
「爲何咱們中止投入 React Native ?」
這是一個更有趣的問題。
想到下面幾點緣由:
咱們已經部署和刪除的 React Native 相關功能再也不須要支持,天然不須要替代者。
咱們進軍 React Native 的哪些方面進展順利?
在咱們使用 React Native 期間,咱們遇到了許多問題。其中一些歸因於咱們的工做流程,一些歸因於咱們的用例,而另外一些則歸因於 React Native 自己。
設計和體驗的挑戰
平臺一致的UI / UX
由於咱們將一些新的屏幕集成到現有更大的用戶體驗當中,因此咱們但願新的 React Native 代碼可以遵循原平生臺模式和現有樣式。這意味着咱們不必定能爲兩個平臺使用相同的 UI 設計。
在 React Native 中確保每一個平臺自身的樣式並不困難,但它確實須要瞭解每一個代碼庫中使用的設計範例。最簡單的是,這須要平臺檢查以及每一個系統的自定義小部件。
對於咱們來講,這一般須要與每一個平臺的開發人員和設計人員溝通,來了解所須要的內容,或者二者都使用單同樣式。這一般會致使 Android 方面的體驗與其餘應用大相徑庭。
一些更復雜的狀況下,須要額外的開發平臺特定代碼來自定義應用體驗。
這樣的例子之一是確保返回/前進按鈕圖標的適配。因爲須要將新的 React Native 功能集成到現有應用當中,爲確保返回/前進圖標和返回按鈕按下的正確行爲,須要針對 React Native 代碼庫修改 Android 特定原生代碼。
原生設計的更改可能須要更改 React Native 代碼以處理集成點
不止一次,Android 應用的導航結構發生變化,這要求咱們更新React Native 代碼。
React Native 功能沒必要被隔離到本身的 Activity 中,而是必須移動到一個 fragment 中,放置在一個帶有BottomNavigationView 的屏幕中,而後在它本身和其餘原生 fragments 之間協調。
這種類型的平臺修改須要返回到單獨的代碼庫,進行更改,更新集成,並確保新修改也不會對 iOS 平臺產生負面影響。
設備特定問題
「碎片化」也好,「多樣化」也罷,不論你怎麼稱呼,留給咱們一個不爭的事實是有更多獨特的 Android 設備配置須要特殊考慮。
咱們屢次發現佈局不適應不一樣尺寸的 Android 手機。咱們發如今最新的 iPhone 或 Pixel 設備上運行流暢的動畫,在 Android 普遍使用的國際市場的低端設備上卻運行不佳。
這些確定不是惟一的 React Native 問題;這些是 Android 上常見的開發挑戰,但隨着平臺特定檢查和考慮因素的增長,咱們不得不開始考慮使用 React Native 實際節省了多少時間。
全球增加
在咱們使用 React Native 的過程當中,國際化成爲 Android 團隊的一個更大的挑戰。咱們有幾個國際辦事處要求實現本地化並減小 apk 大小。
React Native 中的字符串本地化能夠完成,由於它確實須要額外的設置。在咱們的例子中,它須要更改單獨的倉庫。這增長了本地化任務的複雜性,這在尋求其餘團隊的本地化幫助時並不理想。這直接減小了 React Native 功能的本地化頻率。
咱們可以在這段時間減小咱們的 apk 大小,可是包含 React Native 的代碼規模至關大,咱們沒法解決這些問題。刪除最後一個 RN 功能後,咱們的 apk 減少 10M 左右,包括資源刪除和 React Native 自己的剔除。
集成挑戰
與原生組件和導航結構集成
根據咱們的經驗,若是是一個獨立的功能,將 React Native 集成到現有應用程序中可能很是簡單,然而若是須要與現有組件緊密集成並與之通訊,則可能會遇到一些挑戰。
咱們發現本身常常須要大量的橋接代碼實現原生和 React Native 組件之間的通訊。當咱們須要更改 React Native 組件適應咱們的導航層次結構的位置時,相關代碼至少須要一次更新。
工具/構建問題
將 React Native 所需的更新合併到每一個應用的構建過程當中。咱們使用 CircleCI (持續集成工具)來構建咱們須要從新配置的項目,以支持額外的 React Native 構建步驟。
就像前面說的那樣,在 Android 方面,這並不像咱們想象的那樣簡單。
一旦咱們的構建須要更新包含所需的 React Native 任務時,CircleCI 的發佈編譯時間增長大約20%。
從咱們的代碼庫中刪除最終的 React Native 功能後,咱們看到了如下提高:
Android 團隊也遇到過 Android/Gradle 構建工具與 React Native 衝突的問題。最近咱們一直在解決 Gradle 4 版本的問題。
iOS 團隊也面臨着至關大的挑戰。
配置構建很是痛苦,由於咱們的 React Native 的文件結構並不標準。鑑於咱們獨立的項目倉庫,咱們從 srcroot/ReactNative 拉取 React Native 代碼,而且許多現有的構建工具採用了默認的 app 結構,即 /ReactNative/ios/... ios。
此外,咱們使用 cocoapods 進行依賴管理,這是最初建議的融入 React Native 的方式,但在後續已被棄用。咱們非標準的文件結構進一步加重這種狀況,致使咱們不得不在 Podfile 中包含一些使人討厭的黑客式操做,以便能從正確的位置讀取到。
因爲 cocoapods 再也不是包含 React Native 的規範方式,所以 Podfile 更新依賴於要社區去更新,這並不老是同步的。在幾個版本中,css/Yoga 依賴更新掉了,可是 Podfile 卻引用了一個不正確的版本... 最後沒辦法,咱們使用一些黑科技手段解決這種問題。
最後,iOS 項目的 CI(持續集成)也是一個痛點。咱們如今必須添加一個 npm 依賴層,並確保在繼續安裝以前正確更新它們。這爲咱們的構建步驟增長大量的時間。
還有一個引起崩潰的問題,由於一個包含 package.lock
文件的 npm 版本,而另外一個版本沒有包含,致使咱們在 React Native 升級過程當中安裝了不正確的依賴版本。
文檔
React Native 做爲一個生態一直在快速發展,咱們發現文檔常常跟不上。特別是在咱們首次採用時,咱們發現特定版本的文檔/答案可能關聯不上。
關於集成 React Native 到現有項目的文檔在當時彷佛不多。這是咱們更新 CI 構建所面臨挑戰的一個因素。
隨着 React Native 不斷髮展,文檔和支持社區的貢獻獲得了改善。若是咱們今天開始,咱們可能會更容易找到一些問題的答案。
導航
咱們最初使用的是 NavigationExperimental,它不是最容易使用的導航庫。當 ReactNavigation 出現時,它迅速成爲社區普遍接受的導航,而且在 ReactNavigation 真正徹底成熟以前NavigationExperimental 已經被廢棄。
性能
如前所述,有些時候會注意到一些性能問題。
咱們可以製做一些很是漂亮的動畫,這些動畫在規範的 iOS 和 Android 設備上看起來很是不錯,但在國際市場上比較廣泛的低端 Android 設備上卻表現不佳。
進入應用的 React Native 部分時,加載時間比咱們想要的要長。看上去每每不像是無縫過渡。
在對獨立功能4進行原型設計時,繪製渲染性能是一個很是大的問題,以至 React Native 被放棄來達到支持原生體驗。
滯後於原平生臺
由於它不是與 iOS 或 Android 一塊兒構建的,因此 React Native 有時會落後於原平生臺。它一般很大程度上依賴於社區來支持新的原生功能。
其中一個例子就是迫切須要爲 iPhone X 設備提供 SafeArea
支持。咱們最終選擇在短期內不使用 SafeArea
支持該功能。使用 SafeAreaView
是跨平臺開發人員須要瞭解的開發兼容應用程序的平臺特定功能的一個示例。
在其餘時候,React Native 在採用新平臺要求方面落後,例如要求在 2018 年 8 月以前針對 api 26 開發 Android 應用程序。這個需求尚有幾個未解決的問題。
打破更新
React Native 的非向後兼容升級很是使人沮喪。一個例子是當React Native 升級它的底層 React 庫時 PropType 被棄用。
若是再也不維護咱們本身的自定義分支,許多第三方庫就會變得沒法使用。
維護代碼庫的 React Native 部分有時對咱們來講是一個挑戰。如前所述,Android 一般須要額外的工做,不管是與現有代碼集成仍是修復 UI 適配問題。這致使 iOS 和 Android 在 React Native 代碼庫的不一樣分支上工做,所以一個平臺不會減慢另外一個平臺的步伐。
因爲這種分支,代碼的分歧開始慢慢造成,而且使它們達到奇偶校驗所需的努力有所增長。結果,對一個平臺的更新沒有當即添加到另外一個平臺。
React Native 的變化速度也帶來了挑戰。因爲可能會破壞更改,所以更新依賴項以獲取新功能或錯誤修復並不老是很快。
一樣,有時這會致使衝突增長,從而減慢代碼的維護速度。因爲團隊規模小,精力有限,若是它不是 React Native 代碼中的簡單/快速修復,因爲可能須要額外的開發工做,它的處理可能性要低得多。
添加 React Native 以後,並不老是清楚錯誤存在於什麼級別。它是否存在於兩個平臺中?仍是隻在一個平臺上?若是僅在一個平臺上,是在原生代碼仍是 React Native 代碼中?這些問題增長的複雜性有時會減慢質量保證過程。
當須要修復代碼庫的 React Native 部分中的問題時,咱們如今必須同時考慮iOS 和 Android,而且可能使用3個開發堆棧而不是1個。
此外,只有不到100%的團隊感受 React Native 效率很高,可以迅速進入並修復某些東西的開發人員的數量也減小了。
我相信咱們遇到的一些問題是咱們的用例所特有的,可是咱們能夠作些不一樣的事情來緩解其中的一些問題。
減小分歧
咱們本能夠更好地保持每一個應用程序與 React Native repo 中的最新更改保持同步。我相信保持這些更新同步將有助於加強咱們爲這些功能開發更強的真正的跨平臺開發。
在更多的設備上測試,特別是在 Android 上,這樣可以在早期發現更多 UI / 性能問題,並容許咱們在上線以前修復它們。經過在新需求開始工做以前解決問題,這也能夠減小代碼分歧的數量。
更一致的設計
從一開始就更具體的設計方案可能會改善功能的原生外觀。其中一個具體示例是使用與其餘原生應用程序一致的文本/邊距值,而不是在新體驗中選擇新值並在兩個平臺上使用它。
更好的團隊理解
對 React Native 不太熟悉的團隊成員可能已經作了更多努力以適應額外的開發任務。這會增長可以快速解決代碼問題的人數。
我相信咱們團隊中沒有任何人認爲 React Native 沒有它的優勢。我固然相信 React Native 很是適合用例。
你是否須要在兩個平臺上快速從頭開始構建/構建新應用程序?
你是否正在構建一個應用程序/功能,不管平臺如何,其外觀/行爲都相同?
你有沒有想要爲移動設備貢獻的備用開發週期的 Javascript 開發人員?
若是對這些問題中的任何一個回答「是」,React Native 多是你的可行性選擇。
特別是,我認爲若是你有 Javascript/React 的背景,而且正在尋找構建一個不須要太多原生代碼的應用程序,那麼 React Native 是一個很是有吸引力的選擇。它將使您可以開始在移動設備上構建,而無需學習2種不一樣的技術棧。
對於徹底跨平臺應用程序的開發,React Native 也是一個很好的選擇。
iOS 和 Android 團隊在方面意見不一。
iOS
有可能。iOS 團隊一般很高興與 React Native 合做,並考慮使用它構建新功能。此外,在產品方面,咱們產品經理對在 iOS 上運行的 React Native 解決方案比對 Android 更有信心。
Android
不會。理想狀況下,Android 團隊未來不會投入精力到 React Native。咱們發現與 React Native 組件集成的過程很麻煩,而且感受到全部 Android 設備的體驗都不是很好。
此外,還有一種傾向於堅持單一開發技術戰的感受,而不是在Android 框架之上添加新的抽象層和可能的 bugs。
咱們的感受是,React Native 在 Android 上運行新功能的速度更快,但從早期階段到完美版本再到長期維護須要更長的時間。
做爲一個團隊,咱們可能不會在不久的未來投入跨平臺開發。iOS 團隊可使用 React Native 構建一些東西,而且仍然限定於iOS,由於他們團隊一般更喜歡這種體驗。
我的而言,團隊成員會繼續關注 React Native 和 Flutter。隨着 React Native 和 lutter 等解決方案的不斷髮展,咱們將繼續爲咱們的團隊評估它們。
這就是咱們今天所處的境地。
咱們對 React Native 如何適應咱們的團隊和路線圖有了更好的理解。咱們能夠利用這些信息爲咱們團隊的正確技術選擇作出明智的判斷。
「咱們可否明確地說出 React Native 是否適合你?沒有。」
咱們看到了 React Native 的優勢以及侷限性。咱們可否明確地說出 React Native 是否適合你?
沒有。
可是,在評估 React Native 是否適用於你的項目時,但願咱們的經驗能夠做爲幫你帶來一些額外參考點。
相關推薦: 除了Java,爲何你還須要學Kotlin? Airbnb 宣佈棄用 React Native!
關於我:亦楓,博客地址:yifeng.studio/,新浪微博:IT亦楓
微信掃描二維碼,歡迎關注個人我的公衆號:安卓筆記俠
不只分享個人原創技術文章,還有程序員的職場遐想
彩蛋:公衆號回覆關鍵字「面試資料」,獲取 BAT 面試大牛爲你準備的全套面試資料!