facebook的react-native給咱們帶來了用js寫出原生應用的同時,也使得使用RN編寫的代碼的在線升級變得可能,終於能夠不經過應用市場來進行升級,極大的提高了app修bug和賦予新功能的能力。----使用h5的方式也能夠作到,可是rn的用戶體驗可要遠遠超過h5啊。java
通常使用RN編寫的app的線上使用方式,是將react-native bundle命令打出bundle文件和assets文件夾,直接內置到app中,app在viewcontroller或者activity中直接加載app內部的bundle文件,好比下圖。node
當修改了代碼或者圖片的時候,只要app使用新的bundle文件和assets文件夾,就完成了一次在線升級。react
本文主要基於以上思路,講解增量升級的解決方案。android
一個完整的RN-app程序一般包含如下幾個部分:ios
native代碼別想了,無法在線升級,要是能你們就都不使用應用市場ota升級了。git
能進行在線升級的是js代碼部分和圖片資源部分,具體到代碼就是bundle文件和assets文件夾。github
由於在線升級是要走網絡的,咱們要想辦法將網絡消耗降到最低,因此要使用增量升級的方式。算法
針對js代碼部分(即bundle文件)的增量指的是,代碼的改動有多少,增量patch的補丁就有多少,那些沒有改動的代碼部分是不在補丁的範圍內的。json
針對圖片部分(即assets)的增量指的是,升級補丁包中只包含新增的圖片和有改動的圖片。react-native
那麼在app端,下載升級補丁包,只須要和現有的版本進行合併,就能計算出最新版本的全量包。
總結下流程:()中爲例子
首先,計算增量包:新版本(v10) - 舊版本(v1到v9) = 增量包 (會有9個包,v1~v10.zip,v2~v10.zip,,,,,v9-v10.zip)
而後,app根據本身的當前版本(好比V6),下載對應的增量包(V6-V10.zip)。
最後,app中經過 舊版本(v6) + 增量包(v6~v10.zip) = 新版本(v10) ,計算出了新版本的全量包。
assets增量算法,比較簡單,就是比對,能夠很容易的比較出新增的文件,和不一樣的文件(使用md5)。
bundle文件的增量算法,確實比較複雜,剛開始沒有什麼頭緒,後來在leader的指引下,很幸運的找到了google寫的一個開源的庫,能夠對大字符串進行diff和patch,而且支持java、objc、js等等語言,徹底的知足了咱們的需求。
只用到2個接口,具體請參考github上的文檔
google開源庫地址:https://github.com/bystep15/google-diff-match-patch
微軟的codepush也作了相似的事情,不過因爲如下緣由,咱們團隊沒敢使用其做爲解決方案。
不過,codepush客戶端的源碼和文檔也給咱們提供了不少思路,在此感謝codepush團隊。
codepush地址:http://microsoft.github.io/code-push/
本文中通常用min-v或者appMinV表示。
由於js代碼是依賴於native代碼的,因此,jsbundle對app的版本有要求,因此有這個概念。
試想,若是bundle依賴了一個native的一個新的接口,這個接口在v3版本的app中才發佈,若是v2版本的app升級了這個bundle,那麼必然會報錯,嚴重的可能會致使app的崩潰。
存儲全量bundle和生成增量patch
在bundle目錄下放入一個符合要求【參考目錄結構說明】的新版本目錄,好比0.3.0,而後執行如下命令。
命令:node patch 版本號 , 示例:node patch 0.3.0
-d參數: node patch 版本號 -d ,若是加入-d參數,會先刪除patch目錄下的對應版本目錄,而後進行patch生成
而後在patch目錄中就會生成0.3.0的增量包,同時patch目錄下的update.json文件也會從新生成.
在patch目錄下從新生成update.json文件
bundle 存放全量bundle和全量assets的目錄,裏面的文件基本上是使用react-native bundle命令生成的 0.1.0 略 0.2.0 android 略,同ios ios config.json 此版本的配置信息,包含要求app的最低版本等,手動配置 index.jsbundle 全量jsbundle文件,使用react-native bundle命令生成 assets 全量圖片目錄,使用react-native bundle命令生成 0.3.0 略 patch 存放增量補丁的目錄,裏面文件都是命令生成的,無需手動維護 0.1.0 初版本無文件 0.2.0 android 略,同ios ios 0.1.0-0.2.0.zip 增量包.zip 0.3.0 android 略,同ios ios 0.1.0-0.3.0.zip 增量包.zip 0.2.0-0.3.0.zip 增量包.zip update.json 全部的升級包信息 src 存放打包用的源碼 lib 存放打包用依賴的第三方的源碼 patch.js patch命令入口 update.json.js update.json命令入口
{ "v": "0.3.0", //版本 "min-v": "4.0.0", //此版本要求的最小app版本 "date": "2016-01-01", //打包日期 "des": [ "修復xxbug", "添加xx功能" ] }
[ { "v": "0.1.0", "min-v": "4.0.0", "date": "2016-01-01", "des": [ "修復xxbug", "添加xx功能" ], "iosBundleMd5": "11f82563f8fd3f22dccb80ad2297f7bc", "androidBundleMd5": "11f82563f8fd3f22dccb80ad2297f7bc" }, { "v": "0.2.0", "min-v": "4.0.0", "date": "2016-01-01", "des": [ "修復xxbug", "添加xx功能" ], "iosBundleMd5": "3ca2824b008132cee515c0ea29938ff2", "androidBundleMd5": "3ca2824b008132cee515c0ea29938ff2" }, { "v": "0.3.0", "min-v": "4.0.0", "date": "2016-01-01", "des": [ "修復xxbug", "添加xx功能" ], "iosBundleMd5": "dbb81d2383112abb50eb19970c486acd", "androidBundleMd5": "dbb81d2383112abb50eb19970c486acd" } ]
例如:http://localhost:3000/patch/query?bundleV=0.2.0&appV=4.0.0&platform=ios
此接口會有如下4個場景的使用狀況,每一個場景返回的json示例已經提供在後面文檔中。
``` bundleV : app中的bundle版本 appV : app版本 platform : app的平臺 ```
能升級,且能升級到最新版
{ status: 'success', msg: '能夠升級,bundle最新版爲0.3.0', latestBundleV: '0.3.0', latestAppMinV: '4.0.0', canUpdate: true, canUpdateBundleV: '0.3.0', canUpdateAppMinV: '4.0.0', patchUrl: 'patch/0.3.0/ios/0.2.0-0.3.0.zip', platform: 'ios' }
無需升級,已是最新版本
{ status: 'success', msg: '無需升級,已是最新版本', canUpdate: false, platform: 'ios' }
能升級,能升級到當前appMinV的最新bundle版本,但不是最新的bundle,想升最新bundle,必須先升app
{ status: 'success', msg: '能夠升級,但app版本3.0.0過低,只能升到bundleV0.2.0,bundleV最新爲0.3.0', latestBundleV: '0.3.0', latestAppMinV: '4.0.0', canUpdate: true, canUpdateBundleV: '0.2.0', canUpdateAppMinV: '3.0.0', patchUrl: 'patch/0.2.0/ios/0.1.0-0.2.0.zip', platform: 'ios' }
不能升級,已是當前appMinV的最新bundle,但不是最新的bundle,想升最新bundle,必須先升app
{ status: 'success', msg: '不能升級,當前已是app3.0.0的最新bundle了,但不是最新bundle0.3.0,想升級bundle到最新,請先升級app', latestBundleV: '0.3.0', latestAppMinV: '4.0.0', canUpdate: false, platform: 'ios' }
客戶端的主要工做就是發請求到升級服務器詢問是否能升級,而後根據返回的信息,下載升級包,解壓升級包,安裝升級包。
過程當中要保證下載的文件是正確的(md5校驗),要保證補丁安裝以後的全量bundle文件是正確的(md5校驗)。
整個過程用戶無感知。
此部分詳細設計後邊會補充。