在React Native中集成熱更新

最近,在項目DYTT集成了熱更新,簡單來講,就是不用從新下載安裝包便可達到更新應用的目的,也不算教程吧,這裏記錄一下。java

code-push

1.熱更新方案

目前網上大概有兩個比較普遍的方式,分別是react

前者是由ReactNative中文網推出的代碼熱更新服務,後者是由微軟老大哥推出的,固然不只僅是爲React Native,還包括其餘原生方式。android

綜合考慮之下,選擇了react-native-code-pushios

2.安裝code-push

1.安裝code-pushgit

npm install -g code-push-cli

2.註冊登陸帳號github

code-push register

這時候會自動啓動瀏覽器打開網頁並提供一個codePush AccessKey,而後命令行裏出現須要輸入access keyshell

輸入以後就登陸成功了。npm

(貌似在本機上之後都不用登陸了,暫不清楚保持登陸持續多久)react-native

3.添加一個CodePush應用api

code-push app add myProject android react-native
注意填寫app的名稱,OS( android/ ios),平臺( react-native),而且 androidios須要建立兩個應用

建立完成會出現兩個key

name Deployment Key
Production (一串37位的key)
Staging (一串37位的key)

Production是對應生產環境的,Staging是對應開發環境的。

這個對於咱們來講其實沒什麼區別,只是爲了方便測試,因此搞了兩個環境

3.react-native應用接入code-push

1.安裝react-native-code-push

yarn add react-native-code-push

# link
react-native link react-native-code-push

2.原生配置

目前只測試了androidios有興趣的能夠自行測試

上面提到了兩個key值,如今須要配置在原生目錄裏

1.打開android/app/build.gradle

android {
    ...
    buildTypes {
        debug {
            ...
            // Note: CodePush updates should not be tested in Debug mode as they are overriden by the RN packager. However, because CodePush checks for updates in all modes, we must supply a key.
            buildConfigField "String", "CODEPUSH_KEY", '""'
            ...
        }

        releaseStaging {
            ...
            buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'//注意這裏的引號
            ...
        }

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

若是遇到打包錯誤,可加上matchingFallbacks = ['release', 'debug'],不知道是否是個別狀況,若是沒有的請忽略。

修改versionName爲3位數的版本號(code-push要求)

defaultConfig {
        applicationId "com.dytt"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 2
        versionName "2.1.0"//默認爲2位版本號
        // ndk {
        //     abiFilters "armeabi-v7a", "x86"
        // }
    }
release {
            //...
            matchingFallbacks = ['release', 'debug']//加上這一句
            buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"'
            //...
        }

2.打開MainApplication.java

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

這樣就實現了key的動態部署,即在什麼環境下使用什麼key

以上文檔參考自https://github.com/Microsoft/react-native-code-push/blob/master/docs/multi-deployment-testing-android.md

4.客戶端更新策略

1.導入react-native-code-push

這裏須要在應用的根組件上添加CodePush配置

import CodePush from "react-native-code-push";

若是你的環境支持Decorator(修飾符),能夠這樣

@codePush(options: CodePushOptions)
class MyApp extends Component<{}> {}

普通的寫法

class MyApp extends Component<{}> {}
MyApp = codePush(codePushOptions)(MyApp);
export default MyApp;

這裏的codePushOptions是更新的配置選項

  • checkFrequency (codePush.CheckFrequency) 指定您要檢查更新的時間,默認爲codePush.CheckFrequency.ON_APP_START
  • installMode (codePush.InstallMode) 指定什麼時候安裝可選更新,默認爲codePush.InstallMode.ON_NEXT_RESTART
  • ...

詳細的配置可參考https://github.com/Microsoft/react-native-code-push/blob/master/docs/api-js.md

2.更新策略

默認狀況下,CodePush會在app每次啓動的時候去檢測是否有更新,若是有,app會自動下載並在下次打開app時安裝

這種更新方式是靜默的,用戶根本察覺不到。

若是咱們須要給一點更新提示,可使用默認的彈出框,也就是react-native自帶的Alert,點擊後當即安裝

class MyApp extends Component {}
MyApp = codePush({
    updateDialog: true,
    installMode: codePush.InstallMode.IMMEDIATE
})(MyApp);

固然,你能夠對彈出框作少許的自定義,好比標題,按鈕的文字等

updateDialog: {
  optionalIgnoreButtonLabel: '稍後',
  optionalInstallButtonLabel: '當即更新',
  optionalUpdateMessage: '有新版本了,是否更新?',
  title: '更新提示'
},

這些是默認的更新方式,那麼如何自定義呢。

咱們能夠用到CodePush.checkForUpdate來手動檢查更新,而後彈出一個自定義窗口

const RemotePackage = await CodePush.checkForUpdate(deploymentKey);
if(RemotePackage){
  this.modal.init(RemotePackage);//打開彈窗
}
這裏須要注意的是,在 checkForUpdate(或其餘須要填寫deploymentKey的地方)的時候,若是在 debug模式下,若是不填寫 deploymentKey,會提示缺乏 deploymentKey,咱們能夠臨時寫一個固定的方便測試。在正式環境下,這裏是不須要填寫,它會根據系統自動獲取咱們在以前配置的那些 deploymentKey

而後能夠經過RemotePackage.downloadLocalPackage.install來完成下載和安裝

install = async () => {
    LayoutAnimation.easeInEaseOut();
    this.setState({status:1})//download
    const LocalPackage = await this.RemotePackage.download((progress)=>{
        this.setState({
            receivedBytes:progress.receivedBytes
        })
        Animated.timing(
            this.width,
            {
                toValue: parseFloat(progress.receivedBytes / progress.totalBytes).toFixed(2),
                duration: 150
            }
        ).start();
    })
    this.setState({status:2})//downloadComplete
    await LocalPackage.install(LocalPackage.isMandatory?CodePush.InstallMode.IMMEDIATE:CodePush.InstallMode.ON_NEXT_RESUME);
    if(!LocalPackage.isMandatory){
        this.setState({status:3})
        this.setVisible(false);
    }else{
        ToastAndroid && ToastAndroid.show('下次啓動完成更新', ToastAndroid.SHORT);
    }
}

具體實現能夠參考項目DYTT

3.打包Release

cd android

# 生成Release(Production)包
gradlew assembleRelease

# 生成Release(Staging)包
gradlew assembleReleaseStaging

其實都同樣,只是環境區別

5.發佈code-push更新

這一步很簡單,集成了打包和發佈

code-push release-react dyttAndroid android --t 2.1.0 --dev false --d Production --des "1.修復了已知BUG\n 2.測試code push" --m true

這裏注意--t 2.1.0,有如下幾種規則

1.2.3 僅僅只有1.2.3的版本

* 全部版本

1.2.x 主要版本1,次要版本2的任何修補程序版本

1.2.3 - 1.2.7 1.2.3版本到1.2.7版本

>=1.2.3 <1.2.7 大於等於1.2.3版本小於1.2.7的版本

~1.2.3 大於等於1.2.3版本小於1.3.0的版本

^1.2.3 大於等於1.2.3版本小於2.0.0的版本

--d表示開發版本,可選擇ProductionStaging

--m表示是否強制更新

固然還有不少操做,好比刪除某些更新,回滾等,能夠參考官方文檔https://github.com/Microsoft/react-native-code-push

小節

總的來講,此次熱更新集成仍是挺容易,裏面碰到的幾個誤區在上面也已經提到過,歡迎你們多多關注個人項目DYTT^^

相關文章
相關標籤/搜索