React Native 詳細實現熱部署、增量差異化熱更新
本篇文章是React Native中比較經典的內容:熱更新部署。
(一).前言
Android原生App中我們實現熱修復有很多種選擇:Tinker、hotFix、Qzone的熱更新等等。基本的思路都是大同小異的。React Native中的熱更新有點像App的版本更新,也就是根據查詢server端的版本和手機端目前App的版本進行對比,然后來執行是否更新的操作。根本原因在于React Native的加載啟動機制:React Native會將一系列資源打包成js bundle文件,系統加載js bundle文件,解析并渲染。所以,React Native熱更新的根本原理就是更換js bundle文件,并重新加載,新的內容就完美的展示出來了。微軟為我們提供了CodePush來簡化熱更新的操作,但是由于速度等原因在國內并沒有備受青睞。本篇內容就以自己服務器來更新的方式實現。
前面簡單的說了些基本原理,接下來先上一張具體的更新流程圖:
上面流程圖中展示了如何實現更新的步驟,可以總結為如下幾點:
進入App根據版本檢查是否需要更新:
(1)更新:
下載最新JsBundle文件以及所需要的圖片資源等,下載完成后解析最新JsBundle文件。
(2)不更新:
判斷本地是否還有緩存的JsBundle文件:
1>存在:
本地存在JsBundle,即有過熱更新操作。那么App直接加載在緩存目錄下的JsBundle文件。
2>不存在:
本地不存在JsBundle,即之前從未有過熱更新操作。那么App只能使用初始化時打包在assets目錄下的index.android.bundle文件。
Ok,根據上面的流程,我們來看下代碼實現過程:
(二).具體實現
2.1.檢查是否需要更新
實現步驟即請求服務器中的版本號,然后與本地版本號進行對比,此處我為了代碼清晰易懂,直接執行下載更新的流程。
2.2.Android為我們提供了下載工具類:DownLoadManager,我們使用它來執行下載
首先去判斷是否存在有下載的更新壓縮包,如果有,則先刪除舊的,然后下載最新壓縮包。
2.3.下載完成后,DownLoadManager會發出一個DownloadManager.ACTION_DOWNLOAD_COMPLETE的廣播,在收到廣播后,對比下載任務ID
因為我們下載的是Zip壓縮文件( Zip壓縮文件體積下,有效控制了由于更新文件大以及圖片資源占用給用戶帶來消耗流量的問題 ),所以我們需要先解壓
2.4.解壓Zip
2.5.解壓完成后,加載最新Bundle和圖片資源
如何控制RN加載Bundle的方式呢?沒錯,0.26版本之后的RN系統在ReactApplication下的ReactNativeHost為我們提供了getJsBundleFile方法,在該方法中默認返回null,即加載assets下的bundle文件。我們可以根據條件來加載不同目錄下的bundle文件即可
在當我們下載好最新更新文件后,跳轉到RN界面,即會執行getJSBundleFile方法來執行加載Bundle文件的方式。在實際應用當中,我們可以在Splash頁面去執行檢查更新下載,然后在跳轉到RN界面時,最新文件就會呈現出來。
如何獲取最新的bundle文件和圖片資源呢?我們在RN項目根目執行以下命令來得到bundle文件和圖片資源:
react-native bundle --entry-file index.android.js --bundle-output ./bundle/index.android.bundle--platform android--assets-dest./bundle--dev false
(1)--entry 入口js文件,android系統就是index.android.js, iOS 系統就是index.ios.js
(2)--bundle-output 生成的bundle文件路徑
(3)--platform 平臺
(4)--assets-dest 圖片資源的輸出目錄
(5)--dev 是否為開發版本,打正式版的安裝包時我們將其賦值為false
執行命令之前,首先要在根目錄下創建好bundle文件夾,bundle文件和圖片資源將會輸出到已創建好的bundle文件夾下。
解壓后的最新更新文件:
到此,我們便完成了代碼的熱更新工作。
(三).優化補丁包更新
大家可能會說,如果bundle太大的情況下怎么辦呢?沒錯,這個問題同樣在博客開始也提到了。打包成zip也是為了減小更新文件體積,減少用戶流量消耗,同樣,我們也可以生成用生成補丁包的方式來進一步減小更新包zip的體積。
初始項目發布時,生成并保留一份index.android.bundle文件。
有版本更新時,生成新的index.android.bundle文件,使用google-diff-match-patch對比兩個文件,并生成差異補丁文件。app下載補丁文件,再使用google-diff-match-patch和assets目錄下的初始版本合并,生成新的index.android.bundle文件。ok,來看下核心代碼:
3.1.生成補丁包
3.2.下載完成,解壓后執行mergePatAndAsset方法將Assets目錄下的index.android.bundle和pat文件合并
3.3.合并
從上述代碼中我們看到,合并分為如下過程:
(1)獲取Assets目錄下的bundle文件,轉換為字符串
(2)解析.pat文件將其轉換為字符串
(3)調用patch_fromText獲取patches補丁包
(4)調用patch_apply方法將第四步中生成patches補丁包與第一步中獲取的bundle合并生成新的bundle
(5)保存bundle
3.4.讀取pat文件的方法:
3.5.讀取Assets目錄下的bundle文件:
以上步驟執行完成后,我們就獲取到了新的bundle文件,繼而加載新的bundle文件,實現React Native熱更新。
(四).效果演示
為了演示,先來看更新前的界面:
點擊加載最新Bundle,下載最新的,然后加載最新界面:
以上就是使用React Native關于熱更新的內容,其實還有很多不足地方,例如對更新文件進行加密,防止被惡意修改等等一些內容還需要不斷完善。
來自:http://www.lcode.org/react-native-hot-update/