React Native應(yīng)用部署/熱更新-CodePush最新集成總結(jié)

React Native應(yīng)用部署/熱更新-CodePush最新集成總結(jié)(新)

本文出自《React Native學(xué)習(xí)筆記》系列文章拘泞。
了解更多掉冶,可以關(guān)注我的GitHub和加入:
React Native學(xué)習(xí)交流群

React Native學(xué)習(xí)交流群
React Native學(xué)習(xí)交流群


更新說(shuō)明:
此次博文更新適配了最新版的CodePush v1.17.0;添加了iOS的集成方式與調(diào)試技巧柑爸;添加了更為簡(jiǎn)潔的CodePush發(fā)布更新的方式以及進(jìn)行了一些其他的優(yōu)化端圈。

React Native的出現(xiàn)為移動(dòng)開發(fā)領(lǐng)域帶來(lái)了兩大革命性的創(chuàng)新:

  1. 整合了移動(dòng)端APP的開發(fā)盲镶,不僅縮短了APP的開發(fā)時(shí)間,也提高了APP的開發(fā)效率睁冬。
  2. 為移動(dòng)APP動(dòng)態(tài)更新提供了基礎(chǔ)挎春。

本文將向大家分享React Natvie應(yīng)用部署/動(dòng)態(tài)更新方面的內(nèi)容。

React Native支持大家用React Native技術(shù)開發(fā)APP豆拨,并打包生成一個(gè)APP直奋。在動(dòng)態(tài)更新方面React Native只是提供了動(dòng)態(tài)更新的基礎(chǔ),對(duì)將應(yīng)用部署到哪里辽装,如何進(jìn)行動(dòng)態(tài)更新并沒(méi)有支持的那么完善帮碰。好在微軟開發(fā)了CodePush,填補(bǔ)React Native 應(yīng)用在動(dòng)態(tài)更新方面的空白拾积。CodePush 是微軟提供的一套用于熱更新 React Native 和 Cordova 應(yīng)用的服務(wù)殉挽。下面將向大家分享如何使用CodePush實(shí)時(shí)更新你的應(yīng)用,后期會(huì)分享不采用CodePush拓巧,如何自己去實(shí)現(xiàn)React Native應(yīng)用熱更新斯碌。

CodePush簡(jiǎn)介

CodePush 是微軟提供的一套用于熱更新 React Native 和 Cordova 應(yīng)用的服務(wù)。
CodePush 是提供給 React Native 和 Cordova 開發(fā)者直接部署移動(dòng)應(yīng)用更新給用戶設(shè)備的云服務(wù)肛度。CodePush 作為一個(gè)中央倉(cāng)庫(kù)傻唾,開發(fā)者可以推送更新 (JS, HTML, CSS and images),應(yīng)用可以從客戶端 SDK 里面查詢更新承耿。CodePush 可以讓應(yīng)用有更多的可確定性冠骄,也可以讓你直接接觸用戶群。在修復(fù)一些小問(wèn)題和添加新特性的時(shí)候加袋,不需要經(jīng)過(guò)二進(jìn)制打包凛辣,可以直接推送代碼進(jìn)行實(shí)時(shí)更新。

CodePush 可以進(jìn)行實(shí)時(shí)的推送代碼更新:

  • 直接對(duì)用戶部署代碼更新
  • 管理 Alpha职烧,Beta 和生產(chǎn)環(huán)境應(yīng)用
  • 支持 React Native 和 Cordova
  • 支持JavaScript 文件與圖片資源的更新

CodePush開源了react-native版本扁誓,react-native-code-push托管在GitHub上。

安裝與注冊(cè)CodePush

使用CodePush之前首先要安裝CodePush客戶端蚀之。本文以O(shè)SX 10.11.5作為平臺(tái)進(jìn)行演示蝗敢。

安裝 CodePush CLI

管理 CodePush 賬號(hào)需要通過(guò) NodeJS-based CLI。
只需要在終端輸入 npm install -g code-push-cli足删,就可以安裝了寿谴。
安裝完畢后,輸入 code-push -v查看版本壹堰,如看到版本代表成功拭卿。
![安裝 CodePush CLI成功](https://raw.githubusercontent.com/crazycodeboy/RNStudyNotes/master/React%20Native應(yīng)用部署骡湖、熱更新-CodePush最新集成總結(jié)/images/安裝 CodePush CLI成功.png)
目前我的版本是 1.12.1-beta

PS.
npm為NodeJS的包管理器,如果你沒(méi)安裝NodeJS請(qǐng)先安裝峻厚。

創(chuàng)建一個(gè)CodePush 賬號(hào)

在終端輸入code-push register响蕴,會(huì)打開如下注冊(cè)頁(yè)面讓你選擇授權(quán)賬號(hào)。

注冊(cè)codepush
注冊(cè)codepush

授權(quán)通過(guò)之后惠桃,CodePush會(huì)告訴你“access key”浦夷,復(fù)制此key到終端即可完成注冊(cè)。
![獲取codepush access key](https://raw.githubusercontent.com/crazycodeboy/RNStudyNotes/master/React%20Native應(yīng)用部署辜王、熱更新-CodePush最新集成總結(jié)/images/獲取codepush access key.png)
然后終端輸入code-push login進(jìn)行登陸劈狐,登陸成功后,你的session文件將會(huì)寫在 /Users/你的用戶名/.code-push.config呐馆。
登陸成功
登陸成功

PS.相關(guān)命令

  • code-push login 登陸
  • code-push loout 注銷
  • code-push access-key ls 列出登陸的token
  • code-push access-key rm <accessKye> 刪除某個(gè) access-key

在CodePush服務(wù)器注冊(cè)app

為了讓CodePush服務(wù)器知道你的app肥缔,我們需要向它注冊(cè)app: 在終端輸入code-push app add <appName>即可完成注冊(cè)。

code-push-add-app
code-push-add-app

注冊(cè)完成之后會(huì)返回一套deployment key汹来,該key在后面步驟中會(huì)用到续膳。

心得:如果你的應(yīng)用分為Android和iOS版,那么在向CodePush注冊(cè)應(yīng)用的時(shí)候需要注冊(cè)兩個(gè)App獲取兩套deployment key收班,如:

code-push app add MyApp-Android
code-push app add MyApp-iOS

PS.相關(guān)命令

  • code-push app add 在賬號(hào)里面添加一個(gè)新的app
  • code-push app remove 或者 rm 在賬號(hào)里移除一個(gè)app
  • code-push app rename 重命名一個(gè)存在app
  • code-push app list 或則 ls 列出賬號(hào)下面的所有app
  • code-push app transfer 把a(bǔ)pp的所有權(quán)轉(zhuǎn)移到另外一個(gè)賬號(hào)

集成CodePush SDK

Android

下面我們通過(guò)如下步驟在Android項(xiàng)目中集成CodePush坟岔。
第一步:在項(xiàng)目中安裝 react-native-code-push插件,終端進(jìn)入你的項(xiàng)目根目錄然后運(yùn)行
npm install --save react-native-code-push

第二步:在Android project中安裝插件摔桦。
CodePush提供了兩種方式:RNPM 和 Manual社付,本次演示所使用的是RNPM。
運(yùn)行npm i -g rnpm邻耕,來(lái)安裝RNPM鸥咖。

在React Native v0.27及以后版本RNPM已經(jīng)被集成到了 React Native CL中,就不需要再進(jìn)行安裝了兄世。

第三步: 運(yùn)行 rnpm link react-native-code-push扛或。這條命令將會(huì)自動(dòng)幫我們?cè)赼nroid文件中添加好設(shè)置。

react-native-code-push has been successfully linked
react-native-code-push has been successfully linked

在終端運(yùn)行此命令之后碘饼,終端會(huì)提示讓你輸入deployment key,這是你只需將你的deployment Staging key輸入進(jìn)去即可悲伶,如果不輸入則直接單擊enter跳過(guò)即可艾恼。

第四步: 在 android/app/build.gradle文件里面添如下代碼:

apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"  

然后在/android/settings.gradle中添加如下代碼:

include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

第五步: 運(yùn)行 code-push deployment -k ls <appName>獲取 部署秘鑰。默認(rèn)的部署名是 staging麸锉,所以 部署秘鑰(deployment key ) 就是 staging钠绍。
第六步: 添加配置。當(dāng)APP啟動(dòng)時(shí)我們需要讓app向CodePush咨詢JS bundle的所在位置花沉,這樣CodePush就可以控制版本柳爽。更新 MainApplication.java文件:

public class MainApplication extends Application implements ReactApplication {
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    protected boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }
    @Override
    protected String getJSBundleFile() {
      return CodePush.getJSBundleFile();
    }
    @Override
    protected List<ReactPackage> getPackages() {
      // 3. Instantiate an instance of the CodePush runtime and add it to the list of
      // existing packages, specifying the right deployment key. If you don't already
      // have it, you can run "code-push deployment ls <appName> -k" to retrieve your key.
      return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)
      );
    }
  };
  @Override
  public ReactNativeHost getReactNativeHost() {
      return mReactNativeHost;
  }
}

關(guān)于deployment-key的設(shè)置

在上述代碼中我們?cè)趧?chuàng)建CodePush實(shí)例的時(shí)候需要設(shè)置一個(gè)deployment-key,因?yàn)閐eployment-key分生產(chǎn)環(huán)境與測(cè)試環(huán)境兩種,所以建議大家在build.gradle中進(jìn)行設(shè)置媳握。在build.gradle中的設(shè)置方法如下:

打開android/app/build.gradle文件,找到android { buildTypes {} }然后添加如下代碼即可:

android {
    ...
    buildTypes {
        debug {
            ...
            // CodePush updates should not be tested in Debug mode
            ...
        }

        releaseStaging {
            ...
            buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'
            ...
        }

        release {
            ...
            buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"'
            ...
        }
    }
    ...
}

心得:另外,我們也可以將deployment-key存放在local.properties中:

code_push_key_production=erASzHa1-wTdODdPJDh6DBF2Jwo94JFH08Kvb
code_push_key_staging=mQY75RkFbX6SiZU1kVT1II7OqWst4JFH08Kvb

如圖:


local.properties存放codepush-key
local.properties存放codepush-key

然后在就可以在android/app/build.gradle可以通過(guò)下面方式來(lái)引用它了:

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
android {
    ...
    buildTypes {
        debug {
            ...
            // CodePush updates should not be tested in Debug mode
            ...
        }

        releaseStaging {
            ...
            buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'
            ...
        }

        release {
            ...
            buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'
            ...
        }
    }
    ...
}

在android/app/build.gradle設(shè)置好deployment-key之后呢,我們就可以這樣使用了:

@Override
protected List<ReactPackage> getPackages() {
     return Arrays.<ReactPackage>asList(
         ...
         new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line.
         ...
     );
}

第七步:修改versionName。
在 android/app/build.gradle中有個(gè) android.defaultConfig.versionName屬性磷脯,我們需要把 應(yīng)用版本改成 1.0.0(默認(rèn)是1.0蛾找,但是codepush需要三位數(shù))。

android{
    defaultConfig{
        versionName "1.0.0"
    }
}

至此Code Push for Android的SDK已經(jīng)集成完成赵誓。

iOS

CodePush官方提供RNPM打毛、CocoaPods與手動(dòng)三種在iOS項(xiàng)目中集成CodePush的方式,接下來(lái)我就以RNPM的方式來(lái)講解一下如何在iOS項(xiàng)目中集成CodePush俩功。

第一步:在項(xiàng)目中安裝react-native-code-push插件幻枉,終端進(jìn)入你的項(xiàng)目根目錄然后運(yùn)行

npm install --save react-native-code-push

第二步: 運(yùn)行 rnpm link react-native-code-push。這條命令將會(huì)自動(dòng)幫我們?cè)趇os中添加好設(shè)置诡蜓。

在終端運(yùn)行此命令之后熬甫,終端會(huì)提示讓你輸入deployment key,這是你只需將你的deployment Staging key輸入進(jìn)去即可蔓罚,如果不輸入則直接單擊enter跳過(guò)即可椿肩。

關(guān)于deployment-key的設(shè)置

在我們想CodePush注冊(cè)App的時(shí)候,CodePush會(huì)給我們兩個(gè)deployment-key分別是在生產(chǎn)環(huán)境與測(cè)試環(huán)境時(shí)使用的脚粟,我們可以通過(guò)如下步驟來(lái)設(shè)置deployment-key覆旱。

1.用Xcode 打開項(xiàng)目 ? Xcode的項(xiàng)目導(dǎo)航視圖中的PROJECT下選擇你的項(xiàng)目 ? 選擇Info頁(yè)簽 ? 在Configurations節(jié)點(diǎn)下單擊 + 按鈕 ? 選擇Duplicate "Release ? 輸入Staging(名稱可以自定義);

Duplicate-Release-Staging.png
Duplicate-Release-Staging.png

2.然后選擇Build Settings頁(yè)簽 ? 單擊 + 按鈕然后選擇添加User-Defined Setting

添加User-Defined-Setting
添加User-Defined-Setting

3.然后輸入CODEPUSH_KEY(名稱可以自定義)

設(shè)置Staging deployment key
設(shè)置Staging deployment key

提示:你可以通過(guò)code-push deployment ls <APP_NAME> -k命令來(lái)查看deployment key核无。

4.打開 Info.plist文件扣唱,在CodePushDeploymentKey列的Value中輸入$(CODEPUSH_KEY)

引用CODEPUSH_KEY
引用CODEPUSH_KEY

到目前為止,iOS的設(shè)置已經(jīng)完成了团南,和在Android上的集成相比是不是簡(jiǎn)單了很多呢噪沙。

使用CodePush進(jìn)行熱更新

設(shè)置更新策略

在使用CodePush更新你的應(yīng)用之前需要,先配置一下更新控制策略吐根,即:

  • 什么時(shí)候檢查更新正歼?(在APP啟動(dòng)的時(shí)候?在設(shè)置頁(yè)面添加一個(gè)檢查更新按鈕拷橘?)
  • 什么時(shí)候可以更新局义,如何將更新呈現(xiàn)給終端用戶?

最簡(jiǎn)單的方式是在根component中進(jìn)行上述策略控制冗疮。

  1. 在 js中加載 CodePush模塊:
    import codePush from 'react-native-code-push'
    2.在 componentDidMount中調(diào)用 sync方法萄唇,后臺(tái)請(qǐng)求更新
    codePush.sync()

如果可以進(jìn)行更新,CodePush會(huì)在后臺(tái)靜默地將更新下載到本地术幔,等待APP下一次啟動(dòng)的時(shí)候應(yīng)用更新另萤,以確保用戶看到的是最新版本。
如果更新是強(qiáng)制性的,更新文件下載好之后會(huì)立即進(jìn)行更新四敞。
如果你期望更及時(shí)的獲得更新泛源,可以在每次APP從后臺(tái)進(jìn)入前臺(tái)的時(shí)候去主動(dòng)的檢查更新:
在應(yīng)用的根component的componentDidMount中添加如下代碼:

AppState.addEventListener("change", (newState) => {
    newState === "active" && codePush.sync();
});

發(fā)布更新

CodePush支持兩種發(fā)布更新的方式,一種是通過(guò)code-push release-react簡(jiǎn)化方式忿危,另外一種是通過(guò)code-push release的復(fù)雜方式达箍。

第一種方式:通過(guò)code-push release-react發(fā)布更新

這種方式將打包與發(fā)布兩個(gè)命令合二為一,可以說(shuō)大大簡(jiǎn)化了我們的操作流程癌蚁,建議大家多使用這種方式來(lái)發(fā)布更新幻梯。

命令格式:

code-push release-react <appName> <platform>

eg:

code-push release-react MyApp-iOS ios
code-push release-react MyApp-Android android

再來(lái)個(gè)更高級(jí)的:

code-push release-react MyApp-iOS ios  --t 1.0.0 --dev false --d Production --des "1.優(yōu)化操作流程" --m true

其中參數(shù)--t為二進(jìn)制(.ipa與apk)安裝包的的版本;--dev為是否啟用開發(fā)者模式(默認(rèn)為false)努释;--d是要發(fā)布更新的環(huán)境分Production與Staging(默認(rèn)為Staging)碘梢;--des為更新說(shuō)明;--m 是強(qiáng)制更新伐蒂。

關(guān)于code-push release-react更多可選的參數(shù)煞躬,可以在終端輸入code-push release-react進(jìn)行查看。

另外逸邦,我們可以通過(guò)code-push deployment ls <appName>來(lái)查看發(fā)布詳情與此次更新的安裝情況恩沛。

第二中方式:通過(guò)code-push release發(fā)布更新

code-push release發(fā)布更新呢我們首先需要將js與圖片資源進(jìn)行打包成 bundle。

生成bundle

發(fā)布更新之前缕减,需要先把 js打包成 bundle雷客,如:

第一步: 在 工程目錄里面新增 bundles文件:mkdir bundles

第二步: 運(yùn)行命令打包 react-native bundle --platform 平臺(tái) --entry-file 啟動(dòng)文件 --bundle-output 打包js輸出文件 --assets-dest 資源輸出目錄 --dev 是否調(diào)試
eg:
react-native bundle --platform android --entry-file index.android.js --bundle-output ./bundles/index.android.bundle --dev false

生成bundle
生成bundle

需要注意的是:

  • 忽略了資源輸出是因?yàn)?輸出資源文件后桥狡,會(huì)把bundle文件覆蓋了搅裙。
  • 輸出的bundle文件名不叫其他,而是 index.android.bundle裹芝,是因?yàn)?在debug模式下部逮,工程讀取的bundle就是叫做 index.android.bundle。
  • 平臺(tái)可以選擇 android 或者 ios嫂易。

發(fā)布更新

打包bundle結(jié)束后兄朋,就可以通過(guò)CodePush發(fā)布更新了。在終端輸入
code-push release <應(yīng)用名稱> <Bundles所在目錄> <對(duì)應(yīng)的應(yīng)用版本> --deploymentName: 更新環(huán)境 --description: 更新描述 --mandatory: 是否強(qiáng)制更新
eg:
code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章緩存怜械。" --mandatory true

推送更新到CodePush
推送更新到CodePush

注意:

  1. CodePush默認(rèn)是更新 staging 環(huán)境的颅和,如果是staging,則不需要填寫 deploymentName缕允。
  2. 如果有 mandatory 則Code Push會(huì)根據(jù)mandatory 是true或false來(lái)控制應(yīng)用是否強(qiáng)制更新融虽。默認(rèn)情況下mandatory為false即不強(qiáng)制更新。
  3. 對(duì)應(yīng)的應(yīng)用版本(targetBinaryVersion)是指當(dāng)前app的版本(對(duì)應(yīng)build.gradle中設(shè)置的versionName "1.0.6")灼芭,也就是說(shuō)此次更新的js/images對(duì)應(yīng)的是app的那個(gè)版本。不要將其理解為這次js更新的版本般又。
    如客戶端版本是 1.0.6彼绷,那么我們對(duì)1.0.6的客戶端更新js/images巍佑,targetBinaryVersion填的就是1.0.6。
  4. 對(duì)于對(duì)某個(gè)應(yīng)用版本進(jìn)行多次更新的情況寄悯,CodePush會(huì)檢查每次上傳的 bundle萤衰,如果在該版本下如1.0.6已經(jīng)存在與這次上傳完全一樣的bundle(對(duì)應(yīng)一個(gè)版本有兩個(gè)bundle的md5完全一樣),那么CodePush會(huì)拒絕此次更新猜旬。
    如圖:
    對(duì)應(yīng)一個(gè)版本有兩個(gè)bundle的md5完全一樣
    對(duì)應(yīng)一個(gè)版本有兩個(gè)bundle的md5完全一樣

所以如果我們要對(duì)某一個(gè)應(yīng)用版本進(jìn)行多次更新脆栋,只需要上傳與上次不同的bundle/images即可。如:
eg:
對(duì)1.0.6的版本進(jìn)行第一次更新:
code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章緩存洒擦。" --mandatory true
對(duì)1.0.6的版本進(jìn)行第二次更新:
code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.新添加收藏功能椿争。" --mandatory true

  1. 在終端輸入 code-push deployment history <appName> Staging 可以看到Staging版本更新的時(shí)間、描述等等屬性熟嫩。
    eg:
    code-push release Equipment ./bundles 1.0.1

下面我們啟動(dòng)事先安裝好的應(yīng)用秦踪,看有什么反應(yīng):

提示更新
提示更新

應(yīng)用啟動(dòng)之后,從CodePush服務(wù)器查詢更新掸茅,并下載到本地椅邓,下載好之后,提示用戶進(jìn)行更新昧狮。這就是CodePush用于熱更新的整個(gè)過(guò)程景馁。

更多部署APP相關(guān)命令

  • code-push deployment add <appName> 部署
  • code-push deployment rename <appName> 重命名
  • code-push deployment rm <appName> 刪除部署
  • code-push deployment ls <appName> 列出應(yīng)用的部署情況
  • code-push deployment ls <appName> -k 查看部署的key
  • code-push deployment history <appName> <deploymentNmae> 查看歷史版本(Production 或者 Staging)

調(diào)試技巧

如果你用模擬器進(jìn)行調(diào)試CodePush,在默認(rèn)情況下是無(wú)法達(dá)到調(diào)試效果的逗鸣,因?yàn)樵陂_發(fā)環(huán)境下裝在模擬器上的React Native應(yīng)用每次啟動(dòng)時(shí)都會(huì)從NodeJS服務(wù)器上獲取最新的bundle合住,所以還沒(méi)等CodePush從服務(wù)器將更新包下載下來(lái)時(shí),APP就已經(jīng)從NodeJS服務(wù)器完成了更新慕购。

Android

為規(guī)避這個(gè)問(wèn)題在Android可以將開發(fā)環(huán)境的調(diào)試地址改為一個(gè)不可用的地址聊疲,如下圖:

解決NodeJS對(duì)CodePush的影響
解決NodeJS對(duì)CodePush的影響

這樣APP就無(wú)法連接到NodeJS服務(wù)器了,自然也就不能從NodeJS服務(wù)器下載bundle進(jìn)行更新了沪悲,它也只能乖乖的等待從CodePush服務(wù)器下載更新包進(jìn)行更新了获洲。

iOS

在iOS中我們需要上文中講到的生成bundle,將bundle包與相應(yīng)的圖片資源拖到iOS項(xiàng)目中如圖:

導(dǎo)入bundle到xcode
導(dǎo)入bundle到xcode

然后呢殿如,我們需要在AppDelegate.m中進(jìn)行如下修改:

//#ifdef DEBUG
//    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
//#else
    jsCodeLocation = [CodePush bundleURL];
//#endif

讓React Native通過(guò)CodePush去獲取bundle包即可贡珊。

JavaScript API Reference

  • allowRestart
  • checkForUpdate
  • disallowRestart
  • getUpdateMetadata
  • notifyAppReady
  • restartApp
  • sync

其實(shí)我們可以將這些API分為兩類,一類是自動(dòng)模式涉馁,一類是手動(dòng)模式门岔。

自動(dòng)模式

sync為自動(dòng)模式,調(diào)用此方法CodePush會(huì)幫你完成一系列的操作烤送。其它方法都是在手動(dòng)模式下使用的寒随。
codePush.sync
codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress)): Promise<Number>;
通過(guò)調(diào)用該方法CodePush會(huì)幫我們自動(dòng)完成檢查更新,下載,安裝等一系列操作妻往。除非我們需要自定義UI表現(xiàn)互艾,不然直接用這個(gè)方法就可以了。
sync方法讯泣,提供了如下屬性以允許你定制sync方法的默認(rèn)行為

  • deploymentKey (String): 部署key纫普,指定你要查詢更新的部署秘鑰,默認(rèn)情況下該值來(lái)自于Info.plist(Ios)和MianActivity.java(Android)文件好渠,你可以通過(guò)設(shè)置該屬性來(lái)動(dòng)態(tài)查詢不同部署key下的更新昨稼。
  • installMode (codePush.InstallMode): 安裝模式,用在向CodePush推送更新時(shí)沒(méi)有設(shè)置強(qiáng)制更新(mandatory為true)的情況下拳锚,默認(rèn)codePush.InstallMode.ON_NEXT_RESTART即下一次啟動(dòng)的時(shí)候安裝假栓。
  • mandatoryInstallMode (codePush.InstallMode):強(qiáng)制更新,默認(rèn)codePush.InstallMode.IMMEDIATE。
  • minimumBackgroundDuration (Number):該屬性用于指定app處于后臺(tái)多少秒才進(jìn)行重啟已完成更新晌畅。默認(rèn)為0但指。該屬性只在installModeInstallMode.ON_NEXT_RESUME情況下有效。
  • updateDialog (UpdateDialogOptions) :可選的抗楔,更新的對(duì)話框棋凳,默認(rèn)是null,包含以下屬性
    • appendReleaseDescription (Boolean) - 是否顯示更新description,默認(rèn)false
    • descriptionPrefix (String) - 更新說(shuō)明的前綴连躏。 默認(rèn)是” Description: “
    • mandatoryContinueButtonLabel (String) - 強(qiáng)制更新的按鈕文字. 默認(rèn) to “Continue”.
    • mandatoryUpdateMessage (String) - 強(qiáng)制更新時(shí)剩岳,更新通知. Defaults to “An update is available that must be installed.”.
    • optionalIgnoreButtonLabel (String) - 非強(qiáng)制更新時(shí),取消按鈕文字. Defaults to “Ignore”.
    • optionalInstallButtonLabel (String) - 非強(qiáng)制更新時(shí)入热,確認(rèn)文字. Defaults to “Install”.
    • optionalUpdateMessage (String) - 非強(qiáng)制更新時(shí)拍棕,更新通知. Defaults to “An update is available. Would you like to install it?”.
    • title (String) - 要顯示的更新通知的標(biāo)題. Defaults to “Update available”.

eg:

codePush.sync({
      updateDialog: {
        appendReleaseDescription: true,
        descriptionPrefix:'\n\n更新內(nèi)容:\n',
        title:'更新',
        mandatoryUpdateMessage:'',
        mandatoryContinueButtonLabel:'更新',
      },
      mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
      deploymentKey: CODE_PUSH_PRODUCTION_KEY,
    });

手動(dòng)模式

codePush.allowRestart

codePush.allowRestart(): void;
允許重新啟動(dòng)應(yīng)用以完成更新。
如果一個(gè)CodePush更新將要發(fā)生并且需要重啟應(yīng)用(e.g.設(shè)置了InstallMode.IMMEDIATE模式)勺良,但由于調(diào)用了disallowRestart方法而導(dǎo)致APP無(wú)法通過(guò)重啟來(lái)完成更新绰播,
可以調(diào)用此方法來(lái)解除disallowRestart限制。
但在如下四種情況下尚困,CodePush將不會(huì)立即重啟應(yīng)用:

  1. 自上一次disallowRestart被調(diào)用蠢箩,沒(méi)有新的更新。
  2. 有更新事甜,但installModeInstallMode.ON_NEXT_RESTART的情況下谬泌。
  3. 有更新,但installModeInstallMode.ON_NEXT_RESUME逻谦,并且程序一直處于前臺(tái)掌实,并沒(méi)有從后臺(tái)切換到前臺(tái)的情況下。
  4. 自從上次disallowRestart被調(diào)用邦马,沒(méi)有再調(diào)用restartApp贱鼻。

codePush.checkForUpdate

codePush.checkForUpdate(deploymentKey: String = null): Promise<RemotePackage>;
向CodePush服務(wù)器查詢是否有更新宴卖。
該方法返回Promise,有如下兩種值:

  • null 沒(méi)有更新
    通常有如下情況導(dǎo)致RemotePackage為null:

    1. 當(dāng)前APP版本下沒(méi)有部署新的更新版本忱嘹。也就是說(shuō)沒(méi)有想CodePush服務(wù)器推送基于當(dāng)前版本的有關(guān)更新嘱腥。
    2. CodePush上的更新和用戶當(dāng)前所安裝的APP版本不匹配。也就是說(shuō)CodePush服務(wù)器上有更新拘悦,但該更新對(duì)應(yīng)的APP版本和用戶安裝的當(dāng)前版本不對(duì)應(yīng)。
    3. 當(dāng)前APP已將安裝了最新的更新橱脸。
    4. 部署在CodePush上可用于當(dāng)前APP版本的更新被標(biāo)記成了不可用础米。
    5. 部署在CodePush上可用于當(dāng)前APP版本的更新是"active rollout"狀態(tài),并且當(dāng)前的設(shè)備不在有資格更新的百分比的設(shè)備之內(nèi)添诉。
  • A RemotePackage instance
    有更新可供下載屁桑。

eg:

codePush.checkForUpdate()
.then((update) => {
    if (!update) {
        console.log("The app is up to date!");
    } else {
        console.log("An update is available! Should we download it?");
    }
});  

codePush.disallowRestart

codePush.disallowRestart(): void;
不允許立即重啟用于以完成更新。
eg:

class OnboardingProcess extends Component {
    ...

    componentWillMount() {
        // Ensure that any CodePush updates which are
        // synchronized in the background can't trigger
        // a restart while this component is mounted.
        codePush.disallowRestart();
    }

    componentWillUnmount() {
        // Reallow restarts, and optionally trigger
        // a restart if one was currently pending.
        codePush.allowRestart();
    }

    ...
}

codePush.getUpdateMetadata
codePush.getUpdateMetadata(updateState: UpdateState = UpdateState.RUNNING): Promise<LocalPackage>;
獲取當(dāng)前已安裝更新的元數(shù)據(jù)(描述栏赴、安裝時(shí)間蘑斧、大小等)。
eg:

// Check if there is currently a CodePush update running, and if
// so, register it with the HockeyApp SDK (https://github.com/slowpath/react-native-hockeyapp)
// so that crash reports will correctly display the JS bundle version the user was running.
codePush.getUpdateMetadata().then((update) => {
    if (update) {
        hockeyApp.addMetadata({ CodePushRelease: update.label });
    }
});

// Check to see if there is still an update pending.
codePush.getUpdateMetadata(UpdateState.PENDING).then((update) => {
    if (update) {
        // There's a pending update, do we want to force a restart?
    }
});

codePush.notifyAppReady
codePush.notifyAppReady(): Promise<void>;
通知CodePush须眷,一個(gè)更新安裝好了竖瘾。當(dāng)你檢查并安裝更新,(比如沒(méi)有使用sync方法去handle的時(shí)候)花颗,這個(gè)方法必須被調(diào)用捕传。否則CodePush會(huì)認(rèn)為update失敗,并rollback當(dāng)前版本扩劝,在app重啟時(shí)庸论。
當(dāng)使用sync方法時(shí),不需要調(diào)用本方法棒呛,因?yàn)?code>sync會(huì)自動(dòng)調(diào)用聂示。

codePush.restartApp
codePush.restartApp(onlyIfUpdateIsPending: Boolean = false): void;
立即重啟app。
當(dāng)以下情況時(shí)簇秒,這個(gè)方式是很有用的:

  1. app 當(dāng) 調(diào)用 syncLocalPackage.install 方法時(shí)鱼喉,指定的 install modeON_NEXT_RESTARTON_NEXT_RESUME時(shí) 。 這兩種情況都是當(dāng)app重啟或resume時(shí)宰睡,更新內(nèi)容才能被看到蒲凶。
  2. 在特定情況下,如用戶從其它頁(yè)面返回到APP的首頁(yè)時(shí)拆内,這個(gè)時(shí)候調(diào)用此方法完成過(guò)更新對(duì)用戶來(lái)說(shuō)不是特別的明顯旋圆。因?yàn)閺?qiáng)制重啟,能馬上顯示更新內(nèi)容麸恍。

總結(jié)

上文已經(jīng)介紹了CodePush在動(dòng)態(tài)更新方面的一些特性灵巧,但CodePush也存在著一些缺點(diǎn):

  1. 服務(wù)器在國(guó)外搀矫,在國(guó)內(nèi)訪問(wèn),網(wǎng)速不是很理想刻肄。
  2. 其升級(jí)服務(wù)器端程序并不開源的瓤球,后期微軟會(huì)不會(huì)對(duì)其收費(fèi)還是個(gè)未知數(shù)。
    如果在沒(méi)有更好的動(dòng)態(tài)更新React Native應(yīng)用的方案的情況下敏弃,并且這些問(wèn)題還在你的接受范圍之內(nèi)的話卦羡,那么CodePush可以作為動(dòng)態(tài)更新React Native應(yīng)用的一種選擇。
    后期會(huì)向大家分享不采用CodePush麦到,自己搭建服務(wù)器并實(shí)現(xiàn)React Native應(yīng)用的動(dòng)態(tài)更新相關(guān)的方案绿饵。

參考:
http://microsoft.github.io/code-push/docs/getting-started.html
https://github.com/Microsoft/react-native-code-push

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瓶颠,隨后出現(xiàn)的幾起案子拟赊,更是在濱河造成了極大的恐慌,老刑警劉巖粹淋,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吸祟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡桃移,警方通過(guò)查閱死者的電腦和手機(jī)屋匕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谴轮,“玉大人炒瘟,你說(shuō)我怎么就攤上這事〉诓剑” “怎么了疮装?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)粘都。 經(jīng)常有香客問(wèn)我廓推,道長(zhǎng),這世上最難降的妖魔是什么翩隧? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任樊展,我火速辦了婚禮,結(jié)果婚禮上堆生,老公的妹妹穿的比我還像新娘专缠。我一直安慰自己,他們只是感情好淑仆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布涝婉。 她就那樣靜靜地躺著,像睡著了一般蔗怠。 火紅的嫁衣襯著肌膚如雪墩弯。 梳的紋絲不亂的頭發(fā)上吩跋,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音渔工,去河邊找鬼锌钮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛引矩,可吹牛的內(nèi)容都是我干的梁丘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼旺韭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼兰吟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起茂翔,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎履腋,沒(méi)想到半個(gè)月后珊燎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遵湖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年悔政,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片延旧。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谋国,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迁沫,到底是詐尸還是另有隱情芦瘾,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布集畅,位于F島的核電站近弟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏挺智。R本人自食惡果不足惜祷愉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赦颇。 院中可真熱鬧二鳄,春花似錦、人聲如沸媒怯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沪摄。三九已至躯嫉,卻和暖如春纱烘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祈餐。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工擂啥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帆阳。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓哺壶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蜒谤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子山宾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容