React Native 增量升級方案(轉)

前言

facebook的react-native給我們帶來了用js寫出原生應用的同時,也使得使用RN編寫的代碼的在線升級變得可能,終於可以不通過應用市場來進行升級,極大的提升了app修bug和賦予新功能的能力。----使用h5的方式也可以做到,但是rn的用戶體驗可要遠遠超過h5啊。

一般使用RN編寫的app的線上使用方式,是將react-native bundle命令打出bundle文件和assets文件夾,直接內置到app中,app在viewcontroller或者activity中直接加載app內部的bundle文件,比如下圖。

當修改了代碼或者圖片的時候,只要app使用新的bundle文件和assets文件夾,就完成了一次在線升級。

本文主要基於以上思路,講解增量升級的解決方案。

何爲增量?

一個完整的RN-app程序通常包含以下幾個部分:

  1. native代碼部分-objc或者java
  2. js代碼部分-rn代碼、依賴的第三方庫、業務代碼等
  3. 圖片資源部分

native代碼別想了,沒法在線升級,要是能大家就都不使用應用市場ota升級了。

能進行在線升級的是js代碼部分和圖片資源部分,具體到代碼就是bundle文件和assets文件夾。

因爲在線升級是要走網絡的,我們要想辦法將網絡消耗降到最低,所以要使用增量升級的方式。

針對js代碼部分(即bundle文件)的增量指的是,代碼的改動有多少,增量patch的補丁就有多少,那些沒有改動的代碼部分是不在補丁的範圍內的。

針對圖片部分(即assets)的增量指的是,升級補丁包中只包含新增的圖片和有改動的圖片。

那麼在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上的文檔

  1. 生成增量包時候:patch_make(text1, text2) => patches
  2. app生成全量包時候:patch_apply(patches, text1) => [text2, results]

google開源庫地址:https://github.com/bystep15/google-diff-match-patch

codepush

微軟的codepush也做了類似的事情,不過由於以下原因,我們團隊沒敢使用其作爲解決方案。

  1. 其增量升級僅僅是針對圖片資源的
  2. 其升級服務器端程序並不開源
  3. 其升級服務器在美國,國內訪問很慢且不穩定

不過,codepush客戶端的源碼和文檔也給我們提供了很多思路,在此感謝codepush團隊。

codepush地址:http://microsoft.github.io/code-push/

bundle要求的app最小版本

本文中一般用min-v或者appMinV表示。

因爲js代碼是依賴於native代碼的,所以,jsbundle對app的版本有要求,所以有這個概念。

試想,如果bundle依賴了一個native的一個新的接口,這個接口在v3版本的app中才發佈,如果v2版本的app升級了這個bundle,那麼必然會報錯,嚴重的可能會導致app的崩潰。

系統結構設計與各模塊職責

312313123

bundle倉庫設計

存儲全量bundle和生成增量patch

node 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文件也會重新生成.

node 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命令入口

config.json示例

{
  "v": "0.3.0", //版本
  "min-v": "4.0.0", //此版本要求的最小app版本
  "date": "2016-01-01", //打包日期
  "des": [
    "修復xxbug", "添加xx功能"
  ]
}

update.json示例

[
  {
    "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"
  }
]

升級服務器設計

接口patch/query

例如:http://localhost:3000/patch/query?bundleV=0.2.0&appV=4.0.0&platform=ios

此接口會有以下4個場景的使用情況,每個場景返回的json示例已經提供在後面文檔中。

輸入參數

```
bundleV : app中的bundle版本
appV : app版本
platform : app的平臺

```

返回json各項說明

  1. status : 本次請求後臺是否發生了錯誤
  2. msg : 給用戶看的中文提示信息,靜默升級時候沒什麼用
  3. latestBundleV : 當前的最新bundle版本
  4. latestAppMinV : 最新bundle要求的app最低版本
  5. canUpdate : 能否升級,boolean
  6. canUpdateBundleV : 能升級的bundle版本
  7. canUpdateAppMinV : 能升級的bundle要求的app最低版本
  8. patchUrl : 補丁包相對地址
  9. platform : 平臺:ios or android

場景1

能升級,且能升級到最新版

{
   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'
}

場景2

無需升級,已經是最新版本

{
   status: 'success',
   msg: '無需升級,已經是最新版本',
   canUpdate: false,
   platform: 'ios'
}

場景3

能升級,能升級到當前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'
}

場景4

不能升級,已經是當前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'
}

native客戶端設計

客戶端的主要工作就是發請求到升級服務器詢問是否能升級,然後根據返回的信息,下載升級包,解壓升級包,安裝升級包。

過程中要保證下載的文件是正確的(md5校驗),要保證補丁安裝之後的全量bundle文件是正確的(md5校驗)。

整個過程用戶無感知。

此部分詳細設計後邊會補充。

 

原文地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章