繼 Airbnb 之後,Udacity 也宣佈棄用 React Native!

亦楓發表於2018-07-12

Udacity 移動端團隊最近刪除了 App 中使用 React Native 語言開發的相關功能。

我們收到大量有關我們用法或 React Native 的問題以及為什麼我們停止投入資源和精力在 RN 上。

在這篇文章中,我希望能夠回答我們收到的大多數問題並深入瞭解:

  • 我們團隊的規模和組成是什麼?
  • 為什麼我們優先考慮嘗試 React Native?
  • 放棄的原因是什麼?
  • 什麼有用?什麼沒有?
  • ......還有更多[表情]

我當然不會聲稱自己是 React Native 的專家。我們團隊中的其他人比我有更有經驗,但我相信他們也不會自稱專家。

我將根據我們自己的經驗談論在我們的特定情況下做什麼和不做什麼。至於 React Native 是否適合你的團隊/專案取決於你,但希望這篇文章能夠提供額外有用的資料點供你參考。

“React Native 是否適合你的團隊/專案取決於你”

我還是想指出,這些經驗和意見來自 Udacity 的移動工程團隊,而不是其他任何人。這裡的想法並不反映任何其他團隊使用或構建 React 或 React Native 內容的意見。

團隊

首先要搞清楚的事情。我們的團隊是什麼樣的?團隊規模,經驗和所在組織有能力將 React Native 的可行性在專案中產生實際影響。

我們的移動端團隊分佈在 iOS 和 Android 平臺上。

團隊規模

最初引入 React Native 時:

  • 1 名 iOS 開發
  • 2 名 Android 開發
  • 1 名產品經理
  • 1 名設計師

到了今天:

  • 4 名 iOS 開發
  • 3 名 Android 開發
  • 1 名產品經理
  • 1 名設計師

在我們使用 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 經驗。

我們的 Apps

我們的產品是做什麼的?

我們的手機應用旨在為將 Udacity 學習體驗帶到你的手機裝置上。它們支援身份驗證,內容發現,程式註冊(在某些情況下還有支付),最後支援各種程式和內容型別的學習材料的消費。

這些應用也是新的實驗性功能和計劃的試驗場所,目的在於改善使用者的整體學習效果。

程式碼庫規模

  • iOS:97,400 行(.swift,.h,.m 格式)
  • Android:93,000 行(xml,java,kotlin,gradle)

同等

引入 React Native 後,應用程式的功能也非常接近。

隨著時間的推移,核心體驗大致相當,但每個團隊都增加有或多或少的對另一個平臺的經驗。

此外,由於國際需求的擴大,本地化和更小的 apk size 等成為 Android 團隊越來越重視的事情。Android 團隊還與其他地區的團隊密切合作,針對非 iOS 需要考慮的市場特定功能。

為什麼以及我們如何採用 RN

我們為什麼要引入?

我們開始推出全新的移動端專有功能。我們希望在兩個平臺上快速進行實驗和驗證,因此跨平臺開發非常具備吸引力。

因為它是一個新的並且獨立的功能,所以被認為是嘗試跨平臺開發的契機。

選擇 React Native 有幾個原因:

  • 作為跨平臺解決方案提高了可行性
  • 大多數(2/3 的開發人員)團隊適應 Javascript 和 Web 開發
  • 提高了開發速度
  • 來自公司外其他團隊的成功經驗

我們是如何引入的?

最初的 React Native 功能是在一個單獨的 GitHub 倉庫中構建的,並作為 git 子分支分別併入 iOS 和 Android 倉庫。

這樣可以實現非常快速的原型設計,並且如果需要,可以將該功能作為獨立產品釋出。

更多的經驗是原型,最終我們在 React Native 程式碼庫中引入了第二個更大的功能。

時間線

  • 2016年8月:為功能1建立 React Native repo
  • 2016年11月:Android 平臺釋出功能1
  • 2016年11月:功能2開始開發
  • 2016年12月:功能3開始原型設計
  • 2017年1月:功能1開發結束
  • 2017年2月:功能2釋出
  • 2017年3月:功能3原型設計結束
  • 2017年11月:Android 更新功能2
  • 2017年12月:功能4原型作為獨立應用程式。由於效能問題,最終取消了對原生的支援
  • 2018年2月:iOS更新功能2
  • 2018年4月:功能1從 Android 平臺中刪除
  • 2018年6月:從兩個應用中刪除功能2

去除的動機?

答案直截了當。

我們從應用程式中刪除最後的 React Native 程式碼,因為唯一剩下的 React Native 開發的功能已經下線,我們不再需要支援。

“為什麼我們停止投入 React Native ?”

這是一個更有趣的問題。

想到下面幾點原因:

  • 同時在兩個平臺上開發的功能數量減少
  • Android 特定產品需求的增加
  • 對長期維護成本感到失望
  • Android 團隊不傾向繼續使用 React Native

我們用什麼取而代之?

我們已經部署和刪除的 React Native 相關功能不再需要支援,自然不需要替代者。

好的方面?

我們進軍 React Native 的哪些方面進展順利?

  • 入手 React Native 開始在兩個平臺上構建執行確實非常簡單
  • 能夠從更龐大的 React 和 Javascript 生態系統中提取使用很多現有的 librayies 和工具
  • 我們能夠同時在兩個平臺上對功能1進行原型設計
  • 跨平臺團隊的單個開發人員能夠同時為兩個平臺構建大部分功能2
  • 團隊對 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 功能後,我們看到了以下提升:

  • CircleCI 編譯時間從 15min減少到 12min左右
  • 釋出 apk 大小從 28.4MB 降低至 18.1MB

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 作為一個生態一直在快速發展,我們發現文件經常跟不上。特別是在我們首次採用時,我們發現特定版本的文件/答案可能關聯不上。

關於整合 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 也是一個很好的選擇。

我們會再次使用 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 面試大牛為你準備的全套面試資料!

繼 Airbnb 之後,Udacity 也宣佈棄用 React Native!

相關文章