很多时候在实际开发中考虑使用RN的原因不仅仅是因为使用js开发能使得UI界面达到跨平台特性,还有一个重要原因就是热更新方便。对于需要经常使用热更新来发布新版本的App来说,这是RN的一个重大优势。因为RN的热更新非常方便。下面重点讲解下使用微软提供的CodePush来进行热更新。
CodePush简介及其使用命令
CodePush是微软提供一个应用中心云服务平台(CodePush is an App Center cloud service),或许是考虑到RN的影响力,CodePush内部集成了对RN代码的热更新功能,即react-native-code-push。该工具是一个js模块,在命令行运行。所以首先需要安装该模块。
CodePush现在已经被微软移动到了App Center。作为了App Center的一部分,所以可以通过appcenter和codepush 2种方式来推送更新到微软云端服务器了。本文以code-push为例进行讲解。(对appcenter感兴趣的可以参看官方文档:https://docs.microsoft.com/en-us/appcenter/distribution/codepush/cli )
这里只简述下重要步骤,而且以codepush-cli为例进行讲解。每个步骤命令对应的很多其他参数的用法及其他命令请查阅官方文档:https://github.com/Microsoft/code-push/blob/master/cli/README-cn.md
1.安装 code-push CLI: npm install -g code-push-cli
2.使用code-push login命令登陆app center云服务。
如果是初次使用会弹出一个浏览器页面让你创建一个app center账号。直接使用授权登陆方式就可以了。比如使用微软账号授权登陆。登陆之后会得到一个Access token。将这个code粘贴到命令行即可完成注册。
3.在app center云端添加app
code-push app add <appName> <os> <platform> appName是app显示的名称,os是操作系统类型,比如android/ios,platform是平台,比如React-Native,Cordova
如果项目包含了ios和android2个平台的更新,强烈建议在创建app时,appName后面的名称带上操作系统类型后缀,类似如下所示:
appcenter apps create MyApp-Android Android React-Native
因为在后面如果使用code-push release命令发布更新时只能指定更新的app名称而不能指定平台。(code-push release-react可以指定平台)
到这里CodePush的注册和安装就完成了,同时我们往appcenter添加了我们的初始版本的app信息,之后新版本的更新即可推送到该版本的app上。接下来就是在安卓端引入CodePush的SDK了。
在安卓代码中使用CodePush
在客户端使用CodePush的SDK的详细介绍可以参看官方文档:https://docs.microsoft.com/en-us/appcenter/distribution/codepush/react-native
在安卓端使用CodePush包含2个步骤:
- 在项目的根目录执行以下命令
npm install --save react-native-code-push
- 运行react-native link react-native-code-push命令将code-push SDK集成到项目中,该命令执行完成之后在项目的build.gradle文件中会为我们自动配置好使用code-push SDK的一些配置,如下所示:

接下来就可以在java代码中使用微软的CodePush SDK提供的一些类和API接口了。
在MainApplication的ReactNativeHost类的getPackages方法中添加CodePush模块,getJSBundleFile方法返回CodePush获取的bundle路径:
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@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 "appcenter codepush deployment list -a <ownerName>/<appName>" to retrieve your key.
return Arrays.<ReactPackage>asList( new MainReactPackage(),
new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG) );
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();//返回CodePush获取的bundle路径
}
};
在js端代码中增加更新检测逻辑
- 用codePush高阶组件包装根组件:
import codePush from "react-native-code-push";
class MyApp extends Component {
}
MyApp = codePush(MyApp);
- 配置更新规则
默认情况下,CodePush将在每个应用程序启动时检查更新。如果有更新可用,它将被静默下载,并在下一次重新启动时安装。如果你希望修改更新检查规则,可以通过如下方式:
let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
class MyApp extends Component {
}
MyApp = codePush(codePushOptions)(MyApp);
上面这段代码是设置App每次从后台恢复时查询更新。如果你不想自动检查更新,而是当用户点击更新按钮时再检查,那么可以配置checkFrequency为MANUAL即可。如下所示:
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);
更新检测代码基本上是模板代码,关于更新检测更多用法可以直接参看官方示例即可:https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/App.js 大家可以根据自己的需求选择配置项。
发布更新
在安卓端和js端关于CodePush热更新逻辑都完成之后,即可将我们更新后的bundle文件推送给appcenter云端,这样在用户使用我们的app时CodePush SDK就会根据我们在代码中的配置选择更新。主要包括以下2个步骤
关于js打包为bundle的命令,在前面 React Native编译常见问题解决和官方demo分析中讲解常见问题解决时就已经提到过,主要是执行以下命令:
react-native bundle --platform 平台 --dev 是否调试 --entry-file 入口文件 --bundle-output 打包后输出的bundle文件路径 --assets-dest 资源输出目录
如下是一个示例:
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
使用appcenter codepush release命令即可将指定目录的bundle文件推送到微软appcenter云端。该命令用法如下:
<code>code-push release <appName> <updateContents> <targetBinaryVersion> [--deploymentName <deploymentName>] [--description <description>] [--disabled <disabled>] [--mandatory] [--rollout <rolloutPercentage>]</code>
- <appName>:要更新的app名称,这个和我们前面执行add命令时添加的app名称是同一个概念
- <updateContents>:此次要更新的文件的路径,也就是要推送到微软云端的bundle文件路径,可以是单个文件,也可以是目录
- <targetBinaryVersion>:targetBinaryVersion版本号不是指的此次更新的版本号,而是安卓的bulid.gradle中指定的版本号
- --deploymentName参数表示部署key类型,如果不填默认是staging环境的,如果要使用生产环境的key需要使用Production参数。
- --description:此次更新描述,如果在js代码中弹出更新对话框时指定了更新描述,那么会使用此描述
- --mandatory:表示是否强制更新
如下是一个简单示例:
code-push release demo ./bundles/index.android.bundle 1.0.0 --deploymentName Production --description "对bundle文件进行加密" --mandatory true
表示将将./bundles/index.android.bundle路径下的bundle文件推送到app center对应的appName为demo的app下,更新时对用户安装的版本号为1.0.0的app强制更新,更新时提示给用户的更新内容为:“对bundle文件进行加密”。
更简洁的发布更新
微软的code-push release命令是通用的发布更新命令,对于RN而言,还包含一个code-push release-react命令,使用该命令会自动为你生成的应用更新内容(JS包和资源),而不需要你先运行react-native bundle,然后执行code-push release。该命令支持通用发布更新相同的所有参数:
code-push release-react <appName> <platform> [--bundleName <bundleName>] [--deploymentName <deploymentName>] [--description <description>] [--development <development>] [--disabled <disabled>] [--entryFile <entryFile>] [--gradleFile <gradleFile>] [--mandatory] [--noDuplicateReleaseError] [--outputDir <outputDir>] [--plistFile <plistFile>] [--plistFilePrefix <plistFilePrefix>] [--sourcemapOutput <sourcemapOutput>] [--targetBinaryVersion <targetBinaryVersion>] [--rollout <rolloutPercentage>] [--privateKeyPath <pathToPrivateKey>] [--config <config>]
该命令会去自动执行react-native bundle命令生成将要发布到CodePush服务的更新(JS Bundle和资源),同时会自动使用定义在项目文件build.gradle(Android)里的版本名,推断targetBinaryVersion的值(当然你也可以通过--targetBinaryVersion参数指定)。如下是前面那个发布更新的relaese-react版:
code-push release-react demo android --deploymentName Production --description "对bundle文件进行加密" --mandatory true
只需执行一个命令release-react,然后指定一些参数即可完成前面需要2个命令完成的事情。推荐大家使用这种方式对RN进行热更新。
总结
RN热更新可以概括为以下几个步骤:
- 在安卓代码和js代码中引入CodePush SDK设置好热更新逻辑
- 使用react-native模块的命令将更新后的js文件打包为bundle文件
- 使用CodePush的命令来添加app或者推送bundle文件到微软appcenter云端
从上面可以看到RN的热跟新还是非常简单的,这也是RN的一大优势。
文章评论