React Native CodePush實踐小結

前言

CodePush是微軟提供的一套可用於React Native和Cordova的熱更新服務,國內也有相似的服務Pushy,從關注度和使用人數來講,CodePush完勝於Pushy(截至目前,CodePush在Github上Star數2900+,Pushy Star數600+,畢竟大公司的產品更讓開發者內心有底,但CodePush是否真的絕對比Pushy要好不作評價)javascript

CodePush 安裝與註冊

1.安裝 CodePush CLI

使用命令npm install -g code-push-cli安裝CodePush終端html

ps.都在開發React Native了,npm安裝就無需贅言了吧。java

2.註冊CodePush 帳號

CodePush終端安裝完成後就可使用code-push命令了。
在終端輸入code-push register,會跳轉受權網頁。在這個網頁能夠選擇Github。或者微軟做爲受權提供者,不過我以爲90%的開發者都會選擇Github。react

enter description here

受權完成後,CodePush會顯示你的Access Key,複製輸入到終端便可完成註冊並登錄。
ps.只要不主動退出(經過code-push logout命令),登錄狀態會一直有效。android

enter description here

enter description here

在CodePush服務器中建立App

在終端輸入code-push app add <appName>便可完成建立,註冊完成以後會返回一套deployment key,包括Staging和Production。該key在後面步驟中會用到。ios

enter description here

心得:若是你的應用分爲Android和iOS版,那麼在向CodePush註冊應用的時候須要註冊兩個App獲取兩套deployment key,如:
code-push app add AppDemo-Androidgit

code-push app add AppDemo-iOS
由於發佈的時候使用的打包命令是有所不一樣的,所以須要作區分。github

code-push相關常見命令以下:npm

Usage: code-push app <command>
命令:
  add       建立一個新的App
  remove    刪除App
  rm        刪除App
  rename    重命名已經存在App
  list      列出與你帳戶關聯的全部App
  ls        列出與你帳戶關聯的全部App
  transfer  將一個App的全部權轉讓給另外一個賬戶

CodePush集成

這裏跟進使用端分Android集成iOS集成,但兩者都有共通的部分react-native

  • 在React Native項目中安裝codePush依賴:npm install --save react-native-code-push

  • 經過react-native link命令自動構建關聯,這裏會要求輸入 deployment key,直接Enter跳過便可,由於咱們會在後續步驟中經過更加靈活的方式配置

接下來的步驟,AndroidiOS有所不一樣,所以分開來講。

Android端集成

  1. 打開android/app/build.gradle文件,修改android-buildTypes節點成以下

buildTypes {
        debug{
            //省略了其餘配置
            buildConfigField "String", "CODEPUSH_KEY", '""'
        }
        releaseStaging {
            buildConfigField "String", "CODEPUSH_KEY", '"此處填寫Staging key"'
        }
        release {
            //省略了其餘配置
            buildConfigField "String", "CODEPUSH_KEY", '"此處填寫Production key"'
        }
    }
  1. 在android/app/build.gradle設置好deployment-key以後呢,咱們就可使用了:
    修改MainApplication.java文件中的getPackages()方法爲以下:

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

3.修改VersionName
在 android/app/build.gradle中有個 android.defaultConfig.versionName屬性,咱們須要把 應用版本改爲 三位,好比1.0,須要修改爲1.0.0

至此,CodePush在Android端的集成工做已經完成了。

iOS端集成

  1. 使用Xcode打開項目,Xcode的項目導航視圖中的PROJECT下選擇你的項目, 選擇Info頁籤 ,在Configurations節點下單擊 + 按鈕 ,選擇Duplicate "Release Configaration , 輸入Staging。

enter description here

  1. 在build Settings頁籤中單擊 + 按鈕而後選擇添加User-Defined Setting,而後輸入CODEPUSH_KEY(名稱隨意),而後填入deployment key。

ps.能夠經過code-push deployment ls Flow800-Android -k查看deployment key

enter description here

enter description here

3.打開 Info.plist文件,在CodePushDeploymentKey中輸入$(CODEPUSH_KEY),並修改Bundle versions爲三位,以下圖

enter description here

至此,iOS端集成也完成了。

使用react-native-code-psuh進行熱更新

該配置的都已經配置完了,接下來就是使用了。
在使用以前須要考慮的是檢查更新時機,更新是否強制,更新是否要求即時等等。

更新時機

通常常見的應用內更新時機分爲兩種,一種是打開APP就檢查更新,一種是放在設置界面讓用戶主動檢查更新並安裝。

  • 打開APP就檢查更新
    最爲簡單的使用方式在React Natvie的根組件的componentDidMount方法中經過
    codePush.sync()(須要先導入codePush包:import codePush from 'react-native-code-push')方法檢查並安裝更新,若是有更新包可供下載則會在重啓後生效。不過這種下載和安裝都是靜默的,即用戶不可見。若是須要用戶可見則須要額外的配置。具體能夠參考codePush官方API文檔,下面是我的的一些實踐過的配置:

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

上面的配置在檢查更新時會彈出提示對話框, mandatoryxxx表示強制更新,appendReleaseDescription表示在發佈更新時的描述會顯示到更新對話框上讓用戶可見

來個更加接近實際應用的:在用戶點擊檢查更新按鈕後進行檢查,若是有更新則彈出提示框讓用戶選擇是否更新,若是用戶點擊當即更新按鈕,則會進行安裝包的下載(實際上這時候應該顯示下載進度,這裏省略了)下載完成後會當即重啓並生效(也可配置稍後重啓)
ps.這裏面還有個神坑,下文再說。

codePush.checkForUpdate(deploymentKey).then((update) => {
                            if (!update) {
                                Alert.alert("提示", "已經是最新版本--", [
                                    {
                                        text: "Ok", onPress: () => {
                                        console.log("點了OK");
                                    }
                                    }
                                ]);
                            } else {
                                codePush.sync({
                                        deploymentKey: deploymentKey,
                                        updateDialog: {
                                            optionalIgnoreButtonLabel: '稍後',
                                            optionalInstallButtonLabel: '當即更新',
                                            optionalUpdateMessage: '有新版本了,是否更新?',
                                            title: '更新提示'
                                        },
                                        installMode: codePush.InstallMode.IMMEDIATE,

                                    },
                                    (status) => {
                                        switch (status) {
                                            case codePush.SyncStatus.DOWNLOADING_PACKAGE:
                                                console.log("DOWNLOADING_PACKAGE");
                                                break;
                                            case codePush.SyncStatus.INSTALLING_UPDATE:
                                                console.log(" INSTALLING_UPDATE");
                                                break;
                                        }
                                    },
                                    (progress) => {
                                        console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
                                    }
                                );
                            }
                    }

更新是否強制

若是是強制更新須要在發佈的時候指定,發佈命令中配置--m true,下文在細說

更新是否要求即時

在更新配置中經過指定installMode來決定安裝完成的重啓時機,亦即更新生效時機

  • codePush.InstallMode.IMMEDIATE:表示安裝完成當即重啓更新

  • codePush.InstallMode.ON_NEXT_RESTART:表示安裝完成後會在下次重啓後進行更新

  • codePush.InstallMode.ON_NEXT_RESUME:表示安裝完成後會在應用進入後臺後重啓更新

發佈codepush更新包

codepush的更新包發佈其實很簡單。在終端輸入命令

code-push release-react <Appname> <Platform> --t <本更新包面向的舊版本號> --des <本次更新說明>

CodePush默認是更新 Staging 環境的,若是發佈生產環境的更新包,須要指定--d參數:--d Production ,若是發佈的是強制更新包,須要加上 --m true強制更新

示例:

code-push release-react Flow800-Android android --t 2.0.0 --dev false --d Production --des "1.全新頁面\n2.上線流量商城\n3.已知bug修復" --m ture

經常使用部署命令以下:

Usage: code-push deployment <command>
命令:
  add      在已存在的App中建立一個部署
  clear    清除與部署相關的發佈歷史記錄
  remove   在App中刪除一個部署
  rm       在App中刪除一個部署
  rename   重命名一個已存在的部署
  list     列出App中的全部部署
  ls       列出App中的全部部署
  history  列出一個部署的發佈歷史記錄
  h        列出一個部署的發佈歷史記錄

至此,一個完整的發佈,檢查,安裝流程已經基本描述完了。下面來看下更新的效果:

enter description here

實踐經驗小結

  1. 在Android端進行調試時,在更新以前須要修改Debug Server地址和端口爲任意字符串,讓其訪問不到真正Debug Server,不然更新重啓後,就直接訪問了Debug Server致使新的安裝包沒有安裝上。
    enter description here

也能夠直接打Android離線包,這樣子就不須要理會Debug Server的影響

  1. 在iOS端調試時,須要打離線包並拖拽到Xcode工程中。
    打包命令:

react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/main.jsbundle --platform ios --assets-dest ./bundle/ios --dev false

enter description here
拖拽完成後目錄結構如上。
此外,還須要對AppDelegate.m文件進行修改:

enter description here
不然更新重啓後仍是舊版的App。

3.發佈更新包時,切記--t參數指定的是本次更新包的目標版本號,而不是本次更新包的版本號

4.若是不是在根組件的componentDidMount()方法經過codePush.sync()方法進行更新檢查與安裝,好比像我在設置中經過一個檢查更新按鈕,這時候就須要十分當心了。必須在根組件的componentDidMount()方法中添加 codePush.notifyAppReady(),不然應用會出現第一次重啓是更新版,第二次重啓又回滾到舊版的現象。

5.一個App一般不會是一我的開發,所以codePush添加合做者是很常見的。經過 code-push collaborator來操做合做者相關命令。

Usage: code-push collaborator <command>
命令:
  add     對指定的項目添加一個新的合做者
  remove  刪除指定的項目中的合做者
  rm      刪除指定的項目中的合做者
  list    列出指定項目中的全部合做者
  ls      列出指定項目中的全部合做者
示例:
    code-push collaborator add AppDemo foo@bar.com 添加一個合做者foo@bar.com到AppDemo這個App中

6.最後說一下CodePush的缺陷,由於是國外服務器,因此有時候下載速度並非很理想。此外CodePush如今是免費服務,之後會不會收費仍是個未知數。所以已經有人提出了自建codePush服務器,可見於此:code-push-server

更多常見問題及API使用方法請參見如下資料

參考資料

微軟官方ReactNative CodePush文檔
React Native熱更新部署/熱更新-CodePush最新集成總結(新)
react-native-code-push Github基本上全部問題均可以在官方文檔或者github的issue中找到答案。

相關文章
相關標籤/搜索