React Native热更新部署-CodePush(适配Android)

CodePush简介

CodePush是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务。CodePush 是提供给 React Native 和 Cordova 开发者直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。

官方文档:http://microsoft.github.io/code-push/docs/

安装CodePush客户端与注册账号

  • 安装客户端
npm install -g code-push-cli
  • 查看版本
code-push -v
  • 注册账号
code-push register

授权登陆并得到 access key

  • 登陆
code-push login
  • 查看当前登录用户
code-push whoami
  • 注销
code-push logout
  • 列出当前登陆会话
code-push session ls
  • 删除登录会话
code-push session rm <machineName>

访问密钥

  • 假如您不想通过 Github 或者 Microsoft 第三方授权获取 access key,那么可以通过命令方式生成,默认有效期为60天
code-push access-key add "VSTS Integration"
  • 通过 access key 登录
code-push login --accessKey <accessKey>
  • 设置用户名及有效期
code-push access-key patch <accessKeyName> --name "new name" --ttl 10d

CodePush服务器APP管理

  • 添加APP
code-push app add <appName>
  • 分平台添加APP
code-push app add MyApp-Android
code-push app add MyApp-iOS
  • 重命名APP
code-push app rename <appName> <newAppName>
  • 删除APP
code-push app rm <appName>
  • 查看当前账号下APP列表
code-push app ls

部署管理

一个APP名字默认对应两个部署环境:生产环境Production、模拟或演示环境Staging

  • 添加部署环境
code-push deployment add <appName> <deploymentName>
  • 删除及重命名部署环境
code-push deployment rm <appName> <deploymentName>
code-push deployment rename <appName> <deploymentName> <newDeploymentName>
  • 查看指定APP的部署环境
code-push deployment ls <appName> [--displayKeys|-k]

-k 表示显示 Deployment Key

Android集成CodePush、打包、发布更新

参考:https://github.com/Microsoft/react-native-code-push

安装组件

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

链接组件

// React Native v0.27+
react-native link react-native-code-push
// React Native v0.27-
rnpm link react-native-code-push

过程需要输入部署环境 key

使用CodePush更新策略

使用 CodePush 包裹根组件

//ES6
import codePush from "react-native-code-push";

class MyApp extends Component {
}

MyApp = codePush(MyApp);
//ES7
import codePush from "react-native-code-push";

@codePush
class MyApp extends Component {
}
  • 使用更新选项
let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };

class MyApp extends Component {
}

MyApp = codePush(CodePushOptions)(MyApp);
  • 手动更新选项
let codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };

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

    render() {
        <View>
            <TouchableOpacity onPress={this.onButtonPress}>
                <Text>Check for updates</Text>
            </TouchableOpacity>
        </View>
    }
}

MyApp = codePush(CodePushOptions)(MyApp);

Redux Saga for CodePush:react-native-code-push-saga

发布更新

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

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

自动打包js和资源文件成bundle并且上传发布到CodePush的服务器。

也可以自己打包:

react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试

react-native bundle --platform android --entry-file index.android.js --bundle-output ./bundles/index.android.bundle --dev false

然后手动上传:

code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName 更新环境 --description 更新描述 --mandatory 是否强制更新

code-push release CodePushDemo ./bundles/index.android.bundle 1.2.0 --deploymentName Staging --description "支持文章缓存" --mandatory true

多环境部署测试的步骤

客户端的回滚机制可以导致服务器端的回滚:code-push rollback

  • 发布更新到Staging环境:code-push release-react <appName> <platform>
  • 运行Staging版APP,同步更新,验证其是否正常工作
  • 从演示环境推进到生产环境:code-push promote
  • 运行Production版APP,同步更新,验证其是否正常工作

我们注意到第2步与第4步,需要生成两种APP,其实可以整合,但是却是分平台的,这里以Android为例。

配置 Debug 和 Release 模式分别对应 Staging 和 Production 部署环境

(1)使用 Android Studio 打开修改 app/build.gradle,配置 debug下 Staging部署环境的 key和 release下 Production部署环境的 key,然后同步

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

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

(2)修改 MainApplication

protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        //new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG)
        new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG)
    );
}

配置之后,当你调试的时候更新用到的是Staging的key,当签名发布正式包的时候用的就是Production的Key

默认情况下, 用到的是Debug,对应 Staging环境

react-native run android

如果你想测试正式的版本包,即 Production环境,则运行:

react-native run-android --variant release

CodePush 插件的使用场景

CodePush 插件是由两部分组成:

  • 1、js模块
  • 2、原生API

CodePush 使用场景

下面列出CodePush一些常用的用法,你可以选择一个或者组合使用:

Silent sync on app start

// Fully silent update which keeps the app in sync with the server, without ever interrupting the end user
class MyApp extends Component {
}
MyApp = codePush(MyApp);

Silent sync everytime the app resumes

// Sync for updates everytime the app resumes.
class MyApp extends Component {
}
MyApp = codePush({
    checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
    installMode: codePush.InstallMode.ON_NEXT_RESUME
})(MyApp);

Interactive

// Active update, which lets the end user know about each update, and displays it to them immediately after downloading it
class MyApp extends Component {
}
MyApp = codePush({
    updateDialog: true,
    installMode: codePush.InstallMode.IMMEDIATE
})(MyApp);

Log/display progress

// Make use of the event hooks to keep track of the different stages of the sync process.
class MyApp extends Component {
    codePushStatusDidChange(status) {
        switch(status) {
            case codePush.SyncStatus.CHECKING_FOR_UPDATE:
                console.log("Checking for updates.");
                break;
            case codePush.SyncStatus.DOWNLOADING_PACKAGE:
                console.log("Downloading package.");
                break;
            case codePush.SyncStatus.INSTALLING_UPDATE:
                console.log("Installing update.");
                break;
            case codePush.SyncStatus.UP_TO_DATE:
                console.log("Installing update.");
                break;
            case codePush.SyncStatus.UPDATE_INSTALLED:
                console.log("Update installed.");
                break;
        }
    }

    codePushDownloadDidProgress(progress) {
        console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
    }
}
MyApp = codePush(MyApp);

CodePush 属性及回调方法

CodePushOptions 选项对象

CodePushOptions 选项对象可以自定义,其参数包括:

(1) checkFrequency (codePush.CheckFrequency)

检查频率,其值包括:

  • codePush.CheckFrequency.ON_APP_START (0)(默认)
  • codePush.CheckFrequency.ON_APP_RESUME (1)
  • codePush.CheckFrequency.MANUAL (2)

(2) deploymentKey (String)

部署环境 key

(3) installMode (codePush.InstallMode)

可选的安装模式,其值包括:

  • codePush.InstallMode.IMMEDIATE (0)(默认)
  • codePush.InstallMode.ON_NEXT_RESTART (1)
  • codePush.InstallMode.ON_NEXT_RESUME (2)

(4) mandatoryInstallMode (codePush.InstallMode)

强制性的安装模式,其值包括:

  • codePush.InstallMode.IMMEDIATE (0)(默认)
  • codePush.InstallMode.ON_NEXT_RESTART (1)
  • codePush.InstallMode.ON_NEXT_RESUME (2)

(5) minimumBackgroundDuration (Number)

只在 InstallMode.ON_NEXT_RESUME 安装模式下有效,设置更新生效的时间间隔,单位为秒

(6) updateDialog (UpdateDialogOptions)

更新弹窗,包含选项:

  • appendReleaseDescription (Boolean) - false
  • descriptionPrefix (String) - " Description: "
  • mandatoryContinueButtonLabel (String) - "Continue"
  • mandatoryUpdateMessage (String) - "An update is available that must be installed."
  • optionalIgnoreButtonLabel (String) - "Ignore"
  • optionalInstallButtonLabel (String) - "Install"
  • optionalUpdateMessage (String) - "An update is available. Would you like to install it?"
  • title (String) - "Update available"

(7) codePushStatusDidChange

codePushStatusDidChange (event hook)

status code 产生变化的回调,SyncStatus 所有值:

  • codePush.SyncStatus.CHECKING_FOR_UPDATE (0)
  • codePush.SyncStatus.AWAITING_USER_ACTION (1)
  • codePush.SyncStatus.DOWNLOADING_PACKAGE (2)
  • codePush.SyncStatus.INSTALLING_UPDATE (3)
  • codePush.SyncStatus.UP_TO_DATE (4)
  • codePush.SyncStatus.UPDATE_IGNORED (5)
  • codePush.SyncStatus.UPDATE_INSTALLED (6)
  • codePush.SyncStatus.SYNC_IN_PROGRESS (7)
  • codePush.SyncStatus.UNKNOWN_ERROR (-1)

(8) codePushDownloadDidProgress

codePushDownloadDidProgress (event hook)

更新下载过程回调,包含参数:

  • totalBytes (Number)
  • receivedBytes (Number)

实验调试

效果:程序员视角、终端用户视角

报错:The uploaded package is identical to the contents of the specified deployment's current release 表示:已经存在与这次上传完全一样的bundle(对应一个版本有两个bundle的md5完全一样),那么CodePush会拒绝此次更新。

index.android.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Alert,
    Text,
    Image,
    View
} from 'react-native';

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

class CodePushDemo extends Component {
    codePushStatusDidChange(status) {
        switch (status) {
        case codePush.SyncStatus.CHECKING_FOR_UPDATE:
            console.log("Checking for updates.");
            break;
        case codePush.SyncStatus.DOWNLOADING_PACKAGE:
            console.log("Downloading package.");
            break;
        case codePush.SyncStatus.INSTALLING_UPDATE:
            console.log("Installing update.");
            break;
        case codePush.SyncStatus.UP_TO_DATE:
            console.log("Installing update.");
            break;
        case codePush.SyncStatus.UPDATE_INSTALLED:
            console.log("Update installed.");
            break;
        }
    }

    codePushDownloadDidProgress(progress) {
        console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
    }

    componentDidMount() {
        console.log('组件加载后执行');
        //访问慢,不稳定
        codePush.checkForUpdate().then((update) => {
            if (!update) {
                Alert.alert("提示", "已是最新版本", [ {
                    text: "Ok", onPress: () => {
                        console.log("最新版本确定");
                    }
                }]);
            } else {
                codePush.sync({ updateDialog: true, installMode: codePush.InstallMode.IMMEDIATE });
            }
        });
    }

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    Welcome to React Native!
                </Text>
                <Text style={styles.instructions}>
                    To get started, edit index.android.js
                </Text>
                <Text style={styles.instructions}>
                    Double tap R on your keyboard to reload,{'\n'}
                    Shake or press menu button for dev menu
                </Text>
                <Image
                    style={styles.img}
                    resizeMode="contain"
                    source={require('./rnapp.png')}
                    />
                <Text style={styles.author}>Powered by RNAPP.CC</Text>
            </View>
        );
    }
}

CodePushDemo = codePush(CodePushDemo);

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
    img: {
        height: 60,
        width: 332,
        marginTop: 20,
    },
    author: {
        justifyContent: 'flex-end',
        alignItems: 'center',
        marginBottom: 10,
        marginTop: 50,
        textAlign: 'center',
        fontSize: 16,
        color: '#3BC1FF',
    },
});

AppRegistry.registerComponent('CodePushDemo', () => CodePushDemo);

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-hot-update-deployment-codepush-android-compatible/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
React Native热更新部署-CodePush(适配Android)
CodePush简介 CodePush是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务。CodePush 是提供给 React Native 和 Cordova 开发者直接部署移动应用……
<<上一篇
下一篇>>
文章目录
关闭
目 录