當前位置:
首頁 > 最新 > 搜車 React Native 依賴管理方案

搜車 React Native 依賴管理方案

本來準備寫一篇完整的文章介紹下我司的 React Native 整體方案的實踐,但是下筆之後發現話題實在太多太長,很難寫成一篇觀點集中的文章,所以計劃分幾篇文章來介紹,希望對正在或者準備在 RN 上搞事情的同學有所啟發,另外一定要根據自己的業務場景來考慮問題,切勿人云亦云,不知所以。所以本文除了介紹我們最終是怎樣做的之外,我會著重強調「為什麼這樣做」。

本文主要講的是 RN 版本依賴和熱更新相關的話題,這是我們團隊的 RN 方案和業界流行的方案差異最大的地方,也是我們耗費心力最多的部分。本文會先講一下方案的主要思想,然後介紹下場景和緣由,最後詳解一些細節的實現。

下文以 SRN 代表我們團隊的 React Native 方案(souche react native)。

首先介紹核心思想,在我們團隊內部,最開始對 React Native 的版本依賴就達成這樣一個共識:

客戶端版本和 RN 業務版本強依賴,特定客戶端版本會鎖定特定版本的RN業務,RN 業務迭代需要客戶端發版。

同時提供熱更新能力,但是熱更新只能用來 hotfix 修復bug。

其實我們整個方案都是圍繞這兩個重點來實現的,很多同學看到這兩個核心點可能會非常困惑,可能就此結束閱讀此文,但是我是希望大家能夠繼續看下去,看一下為什麼我們要這樣做再做決定。

為什麼發布 RN 業務需要發版?

要討論這個話題,其實首先需要討論一個終極問題:為什麼要引入 RN?不同的團隊可能會給出不同的答案,這都無可厚非,畢竟每個團隊的問題和場景都不同,自然引入一個新技術的理由也不同,唯一最差的理由可能就是「沒有理由」。

對於我們團隊來說,引入 RN 並不是因為它的代碼可以熱更新這個特性,H5代碼自帶遠程屬性,為什麼不用H5而是要用RN?我們的場景,偏B端,重交互而輕營銷,產品關注的主要是穩定性,而不是隨時變化的能力。對於需要靈活變化的場景,用H5完全可以滿足需求,交互和體驗/開發效率都沒有太大問題。所以我後來一直跟大家強調,RN 絕不是用來替換 H5 的。那為什麼要引入 RN 呢,其實在我們正式引入 RN 之前,我們已經在 RN 上積累了半年多,甚至組件庫都做出來了,但是從來沒有在業務中嘗試。後來,有一個契機,公司在C輪之後走向了團隊規模極速擴大的道路,之前我們公司很多B端產品都是重客戶端的,這時候團隊的瓶頸開始凸顯,業務的客戶端開發成本很高,Native的一些缺點開始暴露,例如 開發不夠靈活/跨端技術棧發展不統一/人力成本double(這是最突出的問題),對於需要快速試錯快速迭代的公司階段來說,RN 的優勢凸顯出來了,而這,就是我們引入 RN 的最重要的原因。

想清楚了為什麼要引入 RN 之後,應該如何使用 RN 也就很清楚了,我們並不特別關注 RN 的熱更新能力,而最關注的主要是兩點:

一、如何將 RN 的開發工程化,不管是客戶端開發還是前端開發,都可以用這套方案快速開發普通的業務。

二、穩健性。包含多個方面,底層的穩定,代碼健壯性,版本依賴管理。

第一點,我們之後再講,這是我們整套體系中的一部分,做了很多事情來保證業務可以被快速生產,包括腳手架和開發框架/組件庫等。而第二點,就是文章開頭我們提到的核心思想。

為什麼要強依賴?什麼是強依賴?

我先解釋下,什麼叫做強依賴。一句話表達就是:特定版本的app中某個 RN 業務的bundle的版本也會被鎖定在某個版本,區別於覆蓋式熱更新和H5的實時訪問機制。

為什麼需要這麼做?有以下幾個因素考慮:

其一,跨端依賴。RN 中會大量依賴客戶端的功能,我們的 RN 業務都是內嵌到已經很成熟的APP中(我們公司現在有4個主要的APP),除了 SRN 內部封裝的一些固定的 Native 功能的調用,最主要的是會依賴一些 Native 的協議跳轉,例如 從某個 RN 頁面打開 Native 一個頁面,然後這個 Native 頁面可以再打開另外一個 RN 業務的頁面,具體如何實現的可以改天講,一句話來說就是通過 scheme 協議來做 RN 和 Native 互相的跳轉,這個協議其實就是一個強依賴,如果 RN 新發布了功能,但是客戶端不支持新引入的一個協議,線上客戶端更新了這個 RN 的包,跳轉就會出現問題,此為其一。

其二,底層升級。RN 官方還在快速迭代版本,很多重要功能也在不斷發布,例如 0.43 的 FlatList,如果沒有版本鎖定的功能,可能很難升級底層 SDK 的版本,之前在聽一些分享的時候很多公司都會困擾與此,但是對於我們團隊來說,這裡完全沒有問題,基本可以隨時升級 底層 SDK 的版本,最近我們剛升級到 0.43。當我們要給一個 app 升級底層 SDK 的時候,只需要保證新版本的業務包和SDK兼容即可,無需關心線上已經存在的版本,因為他們依賴的RN bundle 被鎖定在了之前的版本。

其三,功能升級。SRN 出爐後,我們快速上線了十幾個業務,但是後來我們給整個方案加入了很多新功能,例如 Native Bridge 新增方法/bundle 拆分等,這些功能都是不能做到向上兼容的,而對於我們實現的機制,我們也無需考慮向上兼容。另外,最近我們整個發布集成的流程做了很大的改造,但是這種更新我們無需考慮各種版本依賴的問題,只需要考慮新版本 RN 包兼容新方案新SDK即可。

不知道大家在使用覆蓋式熱更新的時候有沒有遇到這些問題,希望能有所啟發。

既然強依賴了,為什麼還有熱更新?

強依賴是個好東西,但是熱更新也是個好東西,我們不能捨本逐末,我們一直在弱化熱更新的優勢,但是不能否認它在某些場景下的必要性,例如緊急修複線上bug,例如一些偏營銷的業務場景,也會通過熱更新帶來快速發布的能力。

但是,我們在熱更新和強依賴之間做出了一個平衡,將二者結合在一起,業務方可以將某個版本的app依賴的某個RN業務鎖定在某個版本,但是這個版本同時也具備熱更新能力,可能很多同學已經猜到了,我們是用兩個版本號來維護這個邏輯的,準確來說並不是兩個版本號,而是一個業界統一的版本格式:語義化版本控制規範(SemVer)。

格式如 $.$.$,遵循 semver 規範的版本號 選擇需要遞增的版本號 major: 主版本號,用於斷代更新或大版本發布 feature: 特性版本號,用於向下兼容的特性新增 patch: 修訂版本號,用於 bug 修復 遞增位的右側位需要清零,如 1.1.2 => 1.2.0

接下來我們就講講這裡的依賴邏輯。

如何鎖定依賴?如何熱更新?

接著上面語義化版本號來講我們的具體實現,可以發現我們需要版本鎖定和熱更新的需求,其實和*SemVer的訴求完全一致,自然而然的,我們用 *$ 來鎖定版本,用 $ 來熱更新,從語義上來說,鎖定版本後需要更新功能需要升級 $ 版本,這就是一個 feature,需要熱更新就是修復問題,升級 $ ,這就是一個 hotfix(or patch)。

最終,其實就是我們的app在用戶手機上運行時,會發起一個熱更新的請求,而這個熱更新的具體邏輯只會判斷「相同 $ 下的最新的 $ 版本號」,本文整篇的精華就是這句話,大家細細體會下。

具體到 SRN 中,其實這個邏輯不是放在客戶端,也不是放在RN代碼中。而是放在一個專門維護版本依賴關係的Node服務中,將整個過程解耦,這樣依賴邏輯可以隨時統一更換。

每個RN業務發布的時候都會講包先上傳到 CDN,然後將這次發布的信息記錄到這個 Node 服務中(如果不小心發錯了版本,在Node服務中操作一下就可以刪掉一次發布),然後每個用戶app啟動的時候,會把用戶本地的所有RN業務包和他們的版本發送給Node服務,Node服務會在服務端判斷 我們剛才提到的這個邏輯,返回「相同 $ 下的最新的 $ 版本號」,然後客戶端就會啟動熱更新邏輯去更新Node服務返回的最新版本的bundle。

這裡還有一點需要提到,其實我們對 $.$.$ 還做了擴展,以便支持測試/開發/預發 環境上的版本,例如測試環境上的版本號會是這樣:0.1.2-beta.8,也就是發布測試版本不會增加 $ 版本,而是會在擴展欄位上增加 $ 版本,對於擴展欄位,因為是開發環境,處理規則是和 $ 版本一樣,直接熱更新,所以除了線上環境,所有其他環境更改代碼都不需要重新定義依賴。

另外一個問題就是這麼複雜的版本規則,如何友好的暴露給開發者?其實對於開發者來說,根本不需要自己維護版本號,也不需要知道這個規則,在業務發布前,腳手架會給選擇,「環境:測試、預發、線上」,「發布類型:功能迭代、bug修復」,這些都是互動式命令,選擇對應命令後,會自動升級當前業務的版本號,自動發布和打tag,無需開發手動維護。

用邏輯圖表示:

等等,是不是少了點什麼?

關於版本依賴鎖定和熱更新其實到這裡基本結束了的,但是仔細深入思考的同學應該發現好像少了點什麼,的確,有這些還不夠,你的整個流程還跑不起來,少了最關鍵的一步:依賴聲明和本地集成

特別是第一次發版的時候,客戶端如何知道當前版本的app依賴了哪些業務和鎖定這個業務的哪個 $ 版本呢?

在開始的時候,我們的方案是在app的工程里維護一個package.json 一樣的文件,內部聲明好 dependence,和 npm 包的 package.json 格式類似。然後在jenkins或者ide里打包app的時候,會執行一段腳本,這個腳本會將這個package.json的內容上傳到剛才提到的 Node 服務中,服務會走一個跟線上熱更新同樣的邏輯,將當前鎖定的$版本的最新$版本返回,然後這個腳本會去下載這個最新的RN bundle,將其直接集成到工程代碼中,並且更新 package.json 內的依賴聲明。

當發布了一個線上bundle的時候,如果選擇了「功能迭代」,會自動給業務的 $ 加一,這時候需要發布新版本的客戶端,就要手動去改一下 package.json 中的這個 bundle 依賴的版本號,例如業務從 1.2.3 到 1.3.0,就把package.json中的版本號改為 1.3.0 ,如果後面你發現有bug又發布了一次,不需要再改 1.3.1 了,打包的時候運行的腳本會自動幫你改掉。也就是每次發版後,這個版的app內都會默認跟一個業務的最新版的bundle。

這樣做看起來挺完美的,但是後來我們發現還是有不少問題的,例如,我們的腳手架沒有把這個版本號的規則太多的暴露給開發者,但是開發者卻需要在每次發版前維護客戶端中的這個依賴,我們的app以及業務發版都很頻繁,造成整個流程不順暢。另外打包的腳本穩定性和運行性能都會影響打包的過程,這個侵入對客戶端和測試同學體驗不好。

現在,我們馬上就會上一個新的方案,原理是將所有RN的包從概念上包裝成 Native的包,例如iOS的pod包,Android的maven包。每次發布的時候,除了之前的流程,現在最後一步,我們會把js bundle分別包裝成一個 iOS 的 pod包,Android 的 maven 包。然後客戶端直接將 RN 的業務當做一個正常的Native業務來使用。

這樣,去掉了兩個動作:app打包時不需要執行集成腳本了,對 app 打包流程沒有任何侵入;另外,不需要在客戶端聲明額外的依賴了,客戶端只需要用傳統的方式,在 podfile 或者 gradle 里聲明依賴就可以,pod包和maven包的版本和RN業務的版本完全一致,規則也一致。

當然,這裡省略了很多細節,如果大家有需要詳細了解的,可以私下聯繫我。

總結

因為有版本依賴鎖定,最近我們的 SRN 整個升級到 0.43 以及 集成 bundle 拆分的功能 還有整個集成過程的徹底改變,都非常輕鬆,升級過程完全無痛,如果大家有遇到同樣的困惑,可以參考一下。後續其實我們也打算在某些偏營銷的場景中,可以不通過發版集成直接在一個app中訪問一個RN業務,其實在現有的機制上做一點小改動即可,還是那句話,看場景,不要徹底否定某些方案,可能只是大家遇到的場景不同,而技術的價值正式解決業務場景中的問題,而不是為了技術而技術。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

Core Graphics,第一部分:序章
無伺服器會成為新的Visual Basic嗎?
怎樣做代碼Review
Core Graphics,第二部分:說說 context

TAG:推酷 |

您可能感興趣

管理vRealize Automation的vPostgres資料庫
Veritas收購雲數據管理公司fluid Operations AG
Pure Storage收購瑞典文件管理軟體公司Cpmpuverde
Vue+VueRouter+elememntUI+axios 搭建後台管理系統
管理髮展 management development
使用Jira software+Structure實現大規模跨團隊項目管理
springboot+vue簡單的後台管理
react+react-router+mobx+element打造管理後台系統
Oracle應用管理云:IMCS添加不同版本Weblogic entity的區別
Windows 上的 SSH?使用 PowerShell Remoting 遠程管理 Windows 伺服器
Kube:在VS Code中管理Helm charts
管理非凡的心智 Managing Brilliant Minds
如何用 Google Tag Manager標籤管理器設置GA onclick按鈕點擊事件
從外部Active Directory獲取域管理員
TomTom Telematics推出新一代車隊管理軟體
在docker for win中使用portainer管理容器
Arm正式宣布收購數據管理公司Treasure Data
linux 使用supervisor管理開機啟動uwsgi
TelephonyManager(電話管理器)
Veritas Velocity數據副本管理技術、原理詳解