rn的問題

在本文章中,Udacity 團(tuán)隊將告訴大家他們使用 React Native 的歷程以及放棄他們的原因,也希望給一些開發(fā)者一些參考和啟發(fā),看自己是否適合使用 React Native。

以下來自 Udacity 移動團(tuán)隊的自述:

Udacity 移動團(tuán)隊

Udacity 的移動團(tuán)隊分為 iOS 和 Android 兩個團(tuán)隊。

團(tuán)隊規(guī)模

在引入 React Native 時:

1 個 iOS 開發(fā)

2 個 Android 開發(fā)者

1 個項目經(jīng)理

1 個設(shè)計師

現(xiàn)在:

4 個 iOS 開發(fā)者

3 個 Android 開發(fā)者

1 個項目經(jīng)理

1 個設(shè)計師

在使用 React Native 的 18 個月中,我們的 iOS 和 Android 團(tuán)隊規(guī)模都有所增長,整個團(tuán)隊由一名項目經(jīng)理來領(lǐng)導(dǎo)。

期間,我們還經(jīng)歷了向多設(shè)計師和多設(shè)計范式轉(zhuǎn)型。

開發(fā)背景

在引入 React Native 時,我們 iOS 團(tuán)隊唯一的開發(fā)人員非常樂于使用 React Native,這極大豐富了他之前 Javascript 和 Web 的開發(fā)經(jīng)驗。兩位 Android 開發(fā)人員中的一位對 Javascript 有豐富的經(jīng)驗,而另一個只有很少的 Javascript、React 或 Web 經(jīng)驗。

現(xiàn)在,四個 iOS 開發(fā)人員中至少有三個非常樂于使用 Javascript 和 React Native。后來加入團(tuán)隊的其他 Android 開發(fā)人員也只有很少的 Javascript 或 Web 經(jīng)驗。

Udacity 的 App

用途

Udacity 的移動 app 旨在將 Udacity 的學(xué)習(xí)體驗帶到用戶的移動設(shè)備上。它支持身份驗證、內(nèi)容發(fā)現(xiàn)、程序注冊(在某些情況還支持支付),以及消費各種類型的學(xué)習(xí)資料。

Udacity 的 App 也作為新的實驗性功能和旨在提升用戶整體學(xué)習(xí)效果的活動的試驗場。

代碼庫的大小

iOS:97,400 行(.swift、.h、.m)

Android:93,000 行(xml、java、kotlin、gradle)

Udacity 為什么以及如何采用 RN ?

為什么要引入它?

當(dāng)時,Udacity 正準(zhǔn)備推出全新的移動端專用功能。我們希望在兩個平臺上快速進(jìn)行實驗和驗證,因此跨平臺具有很大的吸引力。

可以總結(jié)為以下幾點:

跨平臺解決方案具有更高的可行性

大多數(shù)(2/3 開發(fā)人員)團(tuán)隊成員非常適應(yīng) Javascript 和 Web 開發(fā)

可以提高開發(fā)速度

來自公司之外其他團(tuán)隊的成功案例

Udacity 是如何引入的?

React Native 的初始特性是在一個單獨的 GitHub 代碼庫中構(gòu)建的,然后作為 git 子樹分別并入 iOS 和 Android 代碼庫。

這樣可以進(jìn)行非??斓脑驮O(shè)計,并且如果有必要,可以將某些功能作為獨立產(chǎn)品發(fā)布。

Udacity 團(tuán)隊設(shè)計了很多原型,最終在 React Native 代碼庫中引入了第二個更大的功能。

時間線

2016 年 8 月:為功能 1 創(chuàng)建 React Native 代碼庫

2016 年 11 月:在 Android 上發(fā)布了功能 1

2016 年 11 月:開始開發(fā)功能 2

2016 年 12 月:設(shè)計功能 3 原型

2017 年 1 月:功能 1 開發(fā)結(jié)束

2017 年 2 月:功能 2 發(fā)布

2017 年 3 月:功能 3 原型設(shè)計結(jié)束

2017 年 11 月:在 Android 上更新功能 2

2017 年 12 月:功能 4 原型作為獨立 app 發(fā)布。最終由于性能問題取消了對原生的支持

2018 年 2 月:在 iOS 上更新功能 2

2018 年 4 月:從 Android 中移除功能 1

2018 年 6 月:從兩個 app 中移除功能 2

為什么要移除 React Native?

原因很簡單。因為剩下的唯一一個 React Native 功能已經(jīng)沒有用了,我們不再需要支持它。

或許這樣問會更有趣:“為什么我們不繼續(xù)在 React Native 上投入,以便獲得新功能?”

此時,需要考慮幾件事:

1. 同時需要在兩個平臺上構(gòu)建的功能數(shù)量越來越少

2.Android 特定需求在增加

3. 對長期維護(hù)成本感到沮喪

4.Android 團(tuán)隊不愿繼續(xù)使用 React Native

用什么來取代 React Native?

Udacity 移除的 React Native 功能不再受支持,所以不需要進(jìn)行任何替換。

初次嘗試 React Native 給我們帶來哪些好處?

使用 React Native 進(jìn)行跨平臺構(gòu)建非常容易

可以引入 React 和 Javascript 生態(tài)系統(tǒng)中的庫和工具

能夠同時在兩個平臺上對功能進(jìn)行原型設(shè)計

跨職能團(tuán)隊中的單個開發(fā)人員能夠同時為兩個平臺構(gòu)建大部分功能

團(tuán)隊對 React Native 的整體理解有所改善

遇到了哪些問題?

在使用 React Native 期間,我們遇到了很多問,主要在于流程、使用場景,React Native 本身的問題。

設(shè)計和體驗方面的挑戰(zhàn)

平臺一致的 UI/UX

因為要往現(xiàn)有的體驗中加入一些新的頁面,所以我們希望新的 React Native 代碼能夠遵循原生平臺模式和現(xiàn)有的樣式,這意味著我們不一定能為兩個平臺使用相同的 UI 設(shè)計。

要在 React Native 中確保每個平臺本身的樣式并不困難,但確實需要了解每個代碼庫的設(shè)計范式。至少需要對平臺以及每個操作系統(tǒng)的自定義小部件進(jìn)行檢查。

對于我們來說,通常需要與每個平臺的開發(fā)人員和設(shè)計人員溝通,以便了解需求是什么,否則如果兩個平臺使用同一個樣式,有可能會導(dǎo)致在 Android 平臺上的新功能體驗與 App 的其他部分截然不同。

在更復(fù)雜的情況下,需要使用一些額外的平臺特定代碼來自定義 App 體驗。

確?;赝藞D標(biāo)的行為是正確的就是一個例子。由于需要將新的 React Native 功能集成到現(xiàn)有的 app 中,要確保回退圖標(biāo)和后退按鈕按的行為是正確的需要對 Android 原生代碼和 React Native 代碼做出特定的修改。

有一次,Android app 的導(dǎo)航結(jié)構(gòu)發(fā)生了變化,我們不得不修改 React Native 代碼,只是為了要改變原生與 React Native 之間的集成方式。

React Native 不需要有自己的 Activity,我們把它們移到 Fragment 中,并放在帶有 BottomNavigationView 的屏幕中,然后在它和其他原生 Fragment 之間協(xié)調(diào)狀態(tài)。

這種類型的變更需要回到各自的代碼庫,做出更改,更新集成,并確保新的變更不會對 iOS App 產(chǎn)生負(fù)面影響。

設(shè)備特定問題

無論你要把這個叫作“碎片化”還是“多樣化”,我們?nèi)匀灰鎸@樣的事實:越來越多的 Android 設(shè)備有自己獨一無二的配置。

很多時候,我們發(fā)現(xiàn)布局無法完美匹配不同尺寸的 Android 手機(jī),在最新的 iPhone 或 Pixel 設(shè)備上運行流暢的動畫在其他國家(在這些國家 Android 使用更為廣泛)的低端設(shè)備上運行不佳。

這些肯定不只是 React Native 的問題,它們是 Android 平臺開發(fā)常見的問題。但隨著平臺檢查方面的工作量以及需要考慮到的因素數(shù)量的增加,我們不得不開始考慮,React Native 到底可以為我們節(jié)省多少時間。

全球性增長

在我們使用 React Native 期間,國際化成為 Android 團(tuán)隊的一個焦點。我們的幾個國際辦事處要求對 App 進(jìn)行本地化,并減少 apk 大小。

React Native 的字符串本地化完全可以實現(xiàn),盡管確實需要做出一些額外的設(shè)置。在我們的例子中,我們需要對代碼庫做出單獨的修改。這增加了本地化的復(fù)雜性,因為向其他團(tuán)隊尋求本地化幫助并非理想的方式,同時也會降低 React Native 功能的本地化頻率。

我們能夠在一段時間內(nèi)減少 apk 大小,但是 React Native 的大小可能會增加,對此我們無能為力。移除最后一個 React Native 功能后,我們的 apk 大小減少了約 10MB。

集成挑戰(zhàn)

與原生組件和導(dǎo)航結(jié)構(gòu)的集成

根據(jù)我們的經(jīng)驗,對于獨立的功能,將 React Native 集成到現(xiàn)有應(yīng)用程序中可能非常簡單,但如果要與現(xiàn)有組件緊密集成和交互,則可能會麻煩一些。

我們經(jīng)常需要大量的橋接代碼在原生和 React Native 組件之間進(jìn)行通信。在 React Native 組件與現(xiàn)有導(dǎo)航結(jié)構(gòu)集成的地方,每次發(fā)生變更時,都需要進(jìn)行至少一次的橋接代碼更新。

工具 / 構(gòu)建問題

集成 React Native 需要對每個 App 的構(gòu)建過程做出變更。我們使用 CircleCI 來構(gòu)建項目,因此需要對它進(jìn)行重新配置,以支持額外的 React Native 構(gòu)建步驟。

而在 Android 方面,它并不像我們所預(yù)期的那么簡單。

在進(jìn)行重新配置后,CircleCI 的構(gòu)建時間增加了大約 20%。

從代碼庫中移除最后一個 React Native 功能后,我們看到了以下改進(jìn):

CircleCI 構(gòu)建時間從 15 分鐘減少到 12 分鐘

發(fā)布的 apk 大小從 28.4MB 降至 18.1MB

Android 團(tuán)隊也經(jīng)常遇到 Android/Gradle 構(gòu)建工具與 React Native 的沖突問題。

iOS 團(tuán)隊也面臨著相當(dāng)大的挑戰(zhàn)。

配置構(gòu)建過程是一個很痛苦的事,因為我們的構(gòu)建文件結(jié)構(gòu)不是標(biāo)準(zhǔn)的。由于我們使用了單獨的代碼庫,我們在 srcroot/ReactNative 目錄中拉取 React Native 代碼庫,很多現(xiàn)有構(gòu)建工具假設(shè)使用的是默認(rèn)的 app 結(jié)構(gòu),即 /ReactNative/ios/…ios。

此外,我們使用 cocoapods 進(jìn)行依賴管理,最初建議用它來管理 React Native 依賴,但后來被棄用。我們的非標(biāo)準(zhǔn)文件結(jié)構(gòu)也給我們帶來了麻煩,我們不得不在 Podfile 中做一些令人討厭的侵入性修改,讓它從正確的位置讀取配置文件。

由于 cocoapods 不再是標(biāo)準(zhǔn)的 React Native 依賴管理方式,因此 Podfile 的更新只能依賴于社區(qū),而這些更新通常不太同步。比如 css/Yoga 已經(jīng)推出更新,但 Podfile 引用的卻是不正確的版本。最后,我們不得不做出一些侵入性的修改,使用 sed 和正則表達(dá)式來實現(xiàn)版本檢查和安裝。

iOS 項目的 CI 也是一個痛點。我們現(xiàn)在必須添加一個 npm 依賴層,并確保在安裝其他依賴之前它們是最新的。這給我們的構(gòu)建步驟帶來了額外的時間消耗。

還有一個問題會導(dǎo)致構(gòu)建崩潰,比如一個版本的 npm 有package.lock文件,而另一個版本沒有,這會導(dǎo)致我們在 React Native 升級過程中安裝了不正確的依賴版本。

來自 React Native 的挑戰(zhàn)

文檔

React Native 本身發(fā)展得很快,但文檔卻相對缺乏。特別是我們是第一次使用 React Native,我們發(fā)現(xiàn)特定版本的文檔多多少少有點不齊全。

那個時候,用于將 React Native 與現(xiàn)有項目集成的文檔似乎很少,因此,在對 CI 做出構(gòu)建配置時,這無疑增加了我們的難度。

隨著 React Native 不斷發(fā)展,文檔和社區(qū)得到了改善。如果換到了今天,我們或許會更容易找到一些問題的答案。

導(dǎo)航

我們最初使用的是 NavigationExperimental,它不是最容易使用的導(dǎo)航庫。React Navigation 出現(xiàn)后,迅速在社區(qū)中流行開來,在 ReactNavigation 的功能得到真正的完善之前,我們已經(jīng)棄用了 NavigationExperimental。

不過,如果不把一些東西強行組合在一起(例如在呈現(xiàn)模態(tài)流中推送流),有些事情在 ReactNavigation 中是做不到的。

性能

如前所述,我們也會注意到性能問題。

我們能夠制作出一些非常漂亮的動畫,這些動畫在高配置的 iOS 和 Android 設(shè)備上看起來很棒,但在一些低配置 Android 設(shè)備上表現(xiàn)不佳。

進(jìn)入 app 的 React Native 部分時,加載時間比我們預(yù)期的要長,而且它們看起來不像是無縫的過渡。

在對功能 4 進(jìn)行原型設(shè)計時,圖形渲染性能是一個非常大的問題,我們不得不使用原生體驗取代了 React Native。

滯后于原生平臺

因為它不是與 iOS 或 Android 一起構(gòu)建的,所以 React Native 有時會滯后于原生平臺。在很大程度上,它依賴社區(qū)來提供新的原生功能。

其中一個例子就是迫切需要為 iPhone X 提供安全區(qū)域支持。我們最終選擇在短時間內(nèi)不使用 SafeArea,因為 React Native 團(tuán)隊很快就會推出該特性??缙脚_開發(fā)人員在使用 SafeAreaView 開發(fā)兼容性 app 時需要特別注意這個特定于平臺的特性。

有時候,React Native 也會在采用新平臺需求方面表現(xiàn)滯后,例如 Android app 被要求在 2018 年 8 月之前采用 API Level 26。而在這方面還有幾個未解決的問題。

突破性的更新

React Native 無法向后兼容,這點非常令人沮喪。比如,在 React Native 升級了它的底層 React 庫后,PropType 就被棄用了。

如果我們不維護(hù)自己的分支,很多第三方庫就會變得無法使用。

來自維護(hù)方面的挑戰(zhàn)

有時候,維護(hù) React Native 代碼庫對我們來說是一個挑戰(zhàn)。如前所述,Android 通常需要額外的工作,無論是與現(xiàn)有代碼集成還是修復(fù) UI 問題。這導(dǎo)致 iOS 和 Android 使用了不同的 React Native 代碼庫分支,這樣才能讓兩個平臺之間不互相影響。

由于使用了不同的分支,開始出現(xiàn)代碼分歧,并且用于解決沖突的工作流增加了。結(jié)果,對一個平臺的更新并不會立即被添加到另一個平臺中。

React Native 的演化速度也給我們帶來了挑戰(zhàn)。由于可能會出現(xiàn)突破性變更,因此為了獲得新功能或修復(fù) bug 而進(jìn)行的依賴更新的速度變慢了。

另外,有時這會導(dǎo)致摩擦力增加,從而降低了代碼的維護(hù)速度。由于團(tuán)隊規(guī)模小,帶寬有限,如果不是簡單的、可以快速修復(fù)的問題,那么問題就不太可能很快得到解決,因為這可能需要額外的開發(fā)工作量。

因為引入了 React Native,所以我們并不總能清楚地知道 bug 處于什么級別。它是否存在于兩個平臺中?還是只在一個平臺上出現(xiàn)?如果只在一個平臺上出現(xiàn),是在原生代碼中還是在 React Native 代碼中?這些問題所帶來的復(fù)雜性有時候會減慢 QA 過程。

當(dāng)需要修復(fù) React Native 代碼庫中的問題時,我們現(xiàn)在必須同時考慮 iOS 和 Android,并且可能需要使用 3 個開發(fā)棧,而不是 1 個。

此外,不是所有人都覺得 React Native 效率很高,能夠迅速上手并修復(fù)問題的開發(fā)人員的數(shù)量也減少了。

我們本該可以做哪些事情?

我相信,我們遇到的一些問題是我們的場景所固有的,但是我們其實可以做些不一樣的事情來緩解其中的一些問題。

減少代碼分歧

我們本可以更好地讓 React Native 代碼庫中的變更與每個平臺的 App 保持同步。我相信保持這些更新同步將有助于增強我們的跨平臺開發(fā)意識。

多在設(shè)備上進(jìn)行測試,特別是在 Android 上,可能可以在早期就發(fā)現(xiàn)更多的 UI 和性能問題,并在發(fā)布之前修復(fù)它們。在開發(fā)新功能之前解決舊問題,可以減少代碼分歧的數(shù)量。

更一致的設(shè)計

如果從一開始就設(shè)計更具體方案可能有助于改善功能的原生外觀。比如使用與原生 App 一致的文本和邊值,而不是使用新值,并在兩個平臺上使用它們。

團(tuán)隊成員需要學(xué)習(xí)

對 React Native 不太熟悉的團(tuán)隊成員可以更努力地嘗試融入新的開發(fā)棧,這樣就會有更多的人能夠快速解決問題。

適用React Native 的場景?

我相信,我們團(tuán)隊中沒有人會認(rèn)為 React Native 一無是處。我當(dāng)然相信 React Native 有它適合的場景。

你是否需要在兩個平臺上從頭開始快速地構(gòu)建新 app?

你是否正在開發(fā)一個 App 或功能,要求在不同的平臺上具有相同的外觀和行為?

你的 Javascript 開發(fā)人員是不是有多余的時間可用于開發(fā)移動應(yīng)用?

如果對這些問題中的任何一個答案“是”,那么 React Native 很可能適合你。

特別是如果你有 Javascript 和 React 經(jīng)驗,并且正在尋找一個不需要太多原生代碼就能構(gòu)建的應(yīng)用程序,那么 React Native 是一個非常有吸引力的選擇。這樣你就能夠馬上開始開發(fā),而無需去學(xué)習(xí) 2 種不同的技術(shù)棧。

對于新開發(fā)的完全跨平臺的 app,React Native 也是一個很好的選擇。

還會再次使用 React Native 嗎?

iOS 和 Android 團(tuán)隊有不同的意見。

iOS

有可能。iOS 團(tuán)隊通常很樂意使用 React Native,并考慮使用它開發(fā)新功能。此外,在產(chǎn)品方面,我們的 PM 對在 iOS 上運行 React Native 比對 Android 更有信心。

Android

不會。理想情況下,Android 團(tuán)隊將來不會繼續(xù)在 React Native 上投入。我們發(fā)現(xiàn)與 React Native 組件集成的過程很麻煩,并且在 Android 設(shè)備上的體驗達(dá)不到預(yù)期。

此外,還有一種傾向,堅持使用單一的開發(fā)棧,而不是在 Android 框架之上添加新的抽象層,或引入可能的錯誤。

我們的印象是,使用 React Native 開發(fā) Android 新功能的速度更快,但長期來看,新功能從早期階段到能夠完美發(fā)布需要更長的時間。

關(guān)于使用另一種跨平臺解決方案?

從團(tuán)隊方面來看,在不久的將來,我們可能不會在跨平臺開發(fā)上繼續(xù)投入。iOS 團(tuán)隊可以使用 React Native 構(gòu)建一些特定于 iOS 的東西,因為他們通常更喜歡這種體驗。

就個人而言,團(tuán)隊的成員將繼續(xù)關(guān)注 React Native 和 Flutter。隨著 React Native 和 Flutter 等解決方案的不斷發(fā)展,我們也將繼續(xù)對它們做出評估。

我們對 React Native 是否適合我們的團(tuán)隊和路線圖有了更好的理解。在進(jìn)行技術(shù)選型時,我們可以利用這些信息做出更加明智的決策。

我們看到了 React Native 的優(yōu)點以及局限性。我們能否明確地給出 React Native 是否適合你的定論?

不能。

但是,在評估 React Native 是否可用在你們的項目中時,希望我們的經(jīng)驗可以作為參考。

英文原文

https://engineering.udacity.com/react-native-a-retrospective-from-the-mobile-engineering-team-at-udacity-89975d6a8102

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容