react-native热更新 code-push入门。

前言

大约在react-native 0.19版本的的时候开始使用其开发app,转眼之间已经0.49了,今天简单讲下使用codepush热更新。

首先需要说明的是经过多方验证,使用codepush 更新并不违反苹果app store 相关协议,因此能正常审核。
但是需要注意在ios 不要有更新按钮和更新对话框。其他平台商店请查看官方文档。

附带2个本文不相关建议!

  1. 轻易别更新rn0.49.x 由于打包机制的变化,一些库不兼容,需要等待社区适应或者修复bug
  2. https://github.com/wix/react-native-navigation 会修改大量地方,特别是入口,造成一些不兼容,很多插件不能正常link,需要谨慎对待

code-push官方地址: https://github.com/Microsoft/code-push

code-push文档翻译: https://github.com/Microsoft/code-push/blob/master/cli/README-cn.md

准备环境

1.安装react-native基础环境

2.第一步安装

npm install -g code-push-cli

3.登录或者注册,输入下列命令

code-push register 或者code-push login

都会打开浏览器完成注册或者登录,获取到一个token,然后在shell 输入token回车!

可以使用 code-push whoami查看登录状态

切换登录账户先使用code-push logout登出
其他相关详细命令请查看文档

4.注册应用

code-push app add MyApp-ios ios react-native

需要注意的是,不同的平台需要注册不同的应用。

注册结束后会显示当前应用的一对 Deployment Key,请记录下来。Staging 用于测试,Production用于发布

code-push app ls 列出已经注册的应用

code-push app rm MyApp-ios 删除刚刚注册的应用

集成插件

环境准备好那么开始集成react-native-code-push插件

  1. 安装插件

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

  1. link

    执行 react-native link react-native-code-push
    link过程会提醒输入Deployment Key。

低于0.27使用rnpm link react-native-code-push

js 代码更新的时候可以换掉 Deployment Key

  1. 由于一些原因不能自动link 需要手动的请查看下列连接。

[ios整合文档]https://github.com/Microsoft/react-native-code-push/blob/master/docs/setup-ios.md

[android整合文档]https://github.com/Microsoft/react-native-code-push/blob/master/docs/setup-android.md

代码整合

  1. 自动检查更新
    app 入口加入下列代码

下面代码的意思:当app恢复到前台后开始检查更新,如果是必选更新,那么立即更新;如果是可选更新,等下次恢复到前台立即安装更新!

6
1
2
3
4
5
6
7
8
9
10
11
12
import codePush from "react-native-code-push";
let {InstallMode,CheckFrequency} =codePush;
let codePushOptions = {
installMode: InstallMode.ON_NEXT_RESUME,//下次恢复到前台安装更新
mandatoryInstallMode: InstallMode.IMMEDIATE,//如果是必选更新,那么立即更新(会打断用户交互)
checkFrequency: CheckFrequency.ON_APP_RESUME,//检查更新的时机
deploymentKey: 'deploymentKey',//动态改变deploymentKey ,可以不设置,如果不设置使用原生代码内整合的key
updateDialog: null,//无对话框更新
};
AppRegistry.registerComponent('AppStarter', () => codePush(codePushOptions)(App));
  1. 手动更新

在需要更新的地方整合下列代码,调用update 函数开始更新。

先使用checkForUpdate检查更新是因为sync 不一定会触发更新动作。

6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import codePush from "react-native-code-push";
const {SyncStatus} = codePush;
const SYNC_MSG_MAP = {
[SyncStatus.UP_TO_DATE]: "已经是最新了",
[SyncStatus.UPDATE_IGNORED]: "已忽略",
[SyncStatus.UPDATE_INSTALLED]: "安装成功",
[SyncStatus.UNKNOWN_ERROR]: "未知的错误",
[SyncStatus.SYNC_IN_PROGRESS]: "后台已经在更新",
[SyncStatus.CHECKING_FOR_UPDATE]: "再整检查",
[SyncStatus.AWAITING_USER_ACTION]: "等等用户选择",
[SyncStatus.DOWNLOADING_PACKAGE]: "下载中",
[SyncStatus.INSTALLING_UPDATE]: "安装中",
};
const updateDialog={
descriptionPrefix: "内容:",
mandatoryContinueButtonLabel: "立即更新",
mandatoryUpdateMessage: "必须更新",
optionalIgnoreButtonLabel: "忽略",
optionalInstallButtonLabel: "立即更新",
optionalUpdateMessage: "一个更新是可用的。你想要安装它吗?",
title: "检测到更新",
};
function update() {
const {InstallMode, sync, checkForUpdate} = codePush;
checkForUpdate().then((remotePackage) => {
sync({
updateDialog,//更新对话框的文字配置
deploymentKey: 'deploymentKey',//动态改变deploymentKey ,可以不设置,如果不设置使用原生代码内整合的key
installMode: InstallMode.IMMEDIATE,//普通更新立即更新
mandatoryInstallMode: InstallMode.IMMEDIATE//必选更新立即更新
}).then((state) => {
alert(SYNC_MSG_MAP[state] || "未知状态");//显示更新结果提示
}).catch((e) => {
console.log(e)
});
}).catch((e) => {
console.log(e)
});
}

3.获取更新信息和状态

6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import codePush from "react-native-code-push";
function infoToString(info) {
if(!info){
return "";
}
let {appVersion = "", label = "", description = ""} = info;
return `ver:${appVersion},${label},${description}`;
}
function checkUpdate(){
codePush.getUpdateMetadata(codePush.UpdateState.RUNNING)
.then((info) => {
this.setState({
runningInfo: infoToString(info)
})
})
.catch((e) => {
console.log(e)
});
}

UpdateState枚举有3个值

  1. RUNNING 当前运行的包信息
  2. LATEST 服务器上最新的包信息
  3. PENDING 准备更新的包状态,比如下载完成后在等等安装的更新

完整JavaScript api 查看 https://github.com/Microsoft/react-native-code-push/blob/master/docs/api-js.md

发布

整合好了就可以发布更新包,下面的

  1. 发布包

code-push release-react TestApp-ios ios -m --description "修改bug,日常优化。"

-m 表示必须更新的包

  1. 查看安装率

code-push deployment ls TestApp-ios

总结

  1. 我一般会在app 里面整合一个隐藏的更新页面,比如通过点击某个地方10次, 跳转到更新界面查看更新信息和执行手动更新。
  2. Deployment Key可以在js 内替换,可以考虑通过常量控制Deployment Key发布不同的版本
  3. 通过合理使用redux 管理状态,即便是立即更新打断用户也不会对用户输入造成较大影响,但是依然建议谨慎使用立即更新
  4. 在调试模式下也能测试更新