CodePush简介
CodePush 是微软提供的一套提供给 React Native 和 Cordova 开发者,直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。
关于热更新
React Native 官方并没有提供热更新的技术方案,但是它是支持热更新的。
React Native 中的热更新有点像 App 的版本更新,也就是根据查询 server 端的版本和手机端目前 App 的版本进行对比,然后来执行是否更新的操作。
根本原因在于 React Native 的加载启动机制:React Native 会将一系列资源打包成js bundle文件,系统加载js bundle文件,解析并渲染。所以,React Native热更新的根本原理就是更换js bundle文件,并重新加载,新的内容就完美的展示出来了。
一。CodePush热更新组件详细接入教程《安装和RN集成》
1、安装 CodePush CLI
code-push register
这将会启动浏览器,要求验证Github或微软帐号。一旦验证成功,它将创建一个CodePush帐号跟你的Github或MSA相连,并生成一个访问密钥(Access Key),然后你可以拷贝/粘贴到CLI(它会提示你这样做)
如果没有自动打开浏览器,检查设置默认的浏览器
3、//热更新平台的账号信息
register info code-push for android
github username: wq
password: xxxx
4、验证我的登录是否成功
$ code-push login
5、在CodePush服务器注册App(不同平台使用不同的名字)
添加Android平台应用;smallred是你app_name
code-push app add <appName> <os> <platform>
如:
$ code-push app add smallred Android react-native
│ Name │ Deployment Key │
│ Production │ Fhxxx57 │
│ Staging │ atxxx57 │
1-如果你的App既有iOS又有Android,请为不同平台创建单独的App;
2-成功,会返回Deployment Key。
3-所有新的Apps自动会出现2个部署环境:staging代表开发版的热更新部署,用于测试更新;production代表生产版的。
4-在ios中,将staging的key复制在info.plist的CodePushDeploymentKey值中
在android中,复制在Application的getPackages的CodePush构造中。
ps:你可以通过code-push deployment ls <app_name> -k命令来查看deployment key。
我们可以输入如下命令来查看我们刚刚添加的App
$ code-push app list
二、RN代码中集成CodePush的SDK
1.在根目录(项目目录)执行安装集成的组件react-native-code-push
react-native link react-native-code-push
至此Code Push for Android的SDK已经集成完成。
2.在android中配置参数
在 android/app/build.gradle文件里面添如下代码:
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
然后在/android/settings.gradle中添加如下代码:
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
3.运行 code-push deployment -k ls <appName>获取 部署秘钥。默认的部署名是 staging,所以 部署秘钥(deployment key ) 就是 staging。
code-push deployment -k ls smallred
如果之前的都配置正确,那这里可以看到Production与Staging的Deployment Key,
将这两个key粘贴下来.如果环境来决定需要用到哪个key.
在刚开始,肯定需要测试,
那就将Staging对应的Deployment Key,替换到下面deployment-key-here的代码中.
地址:https://www.jianshu.com/p/87ccfb795635
4.添加配置。当APP启动时我们需要让app向CodePush咨询JS bundle的所在位置,这样CodePush就可以控制版本。更新 MainApplication.java文件:
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@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 "code-push deployment ls <appName> -k" to retrieve your key.
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new CodePush("atxxx57", MainApplication.this, BuildConfig.DEBUG),
//new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
关于deployment-key的设置
在上述代码中我们在创建CodePush实例的时候需要设置一个deployment-key,因为deployment-key分生产环境与测试环境两种,所以建议大家在build.gradle中进行设置。在build.gradle中的设置方法如下:
打开android/app/build.gradle文件,找到android { buildTypes {} }然后添加如下代码即可:
android {
...
buildTypes {
debug {
...
// CodePush updates should not be tested in Debug mode
...
}
releaseStaging {
...
buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'
...
}
release {
...
buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"'
...
}
}
...
}
心得:另外,我们也可以将deployment-key存放在local.properties中:
code_push_key_production=Fhxxx57
code_push_key_staging=atxxx57
然后在就可以在android/app/build.gradle可以通过下面方式来引用它了:
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
android {
...
buildTypes {
debug {
...
// CodePush updates should not be tested in Debug mode
...
}
releaseStaging {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'
...
}
release {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'
...
}
}
...
}
在android/app/build.gradle设置好deployment-key之后呢,我们就可以这样使用了:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
...
new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line.
...
);
}
5.修改versionName。
在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。
android{
defaultConfig{
versionName "1.0.0"
}
}
详细的操作在官网demo示例中:
https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/App.js
三。配置Android平台《发布更新》
7、发布更新RN的bundle到微软服务器
CodePush支持两种发布更新的方式:
一是通过code-push release-react简化方式,
二是通过code-push release的复杂方式。
一简化方式、命令格式:
code-push release-react <appName> <platform>
如eg:
code-push release-react smallred ios
code-push release-react smallred android
code-push release-react smallred ios --t 1.0.0 --dev false --d Production --des "1.优化操作流程" --m true
code-push release-react smallred android --t 1.0.0 --dev false --d Production --des "1.优化操作流程" --m true
[--bundleName <bundleName>] 指明生成JS Bundle的文件名
[--deploymentName <deploymentName>] 部署环境名:Staging(临时环境)、Production(生产环境)
[--description <description>] 更新内容描述
[--development <development>] 指明是否要生成一个非最小化,开发的JS bundle文件。默认是false,禁用警告提示并且bundle文件是最小化的。
[--disabled <disabled>] 指明一个版本更新是否可以被用户下载。如果没有指定,版本更新是有效的(如:用户将要下载的那一刻你的应用称为同步
)。如果你想发布一个更新但不是立即生效,那么这个参数是有价值的,直到你明确用[补丁]发布,当你要让用户能够下载(如:公告博客上线)。
[--entryFile <entryFile>] 指明相对应用根目录的路径入口JavaScript 文件。
[--mandatory] 更新是否强制性(true、false)
[--sourcemapOutput <sourcemapOutput>] 指明生成的JS bundle 的sourcemap写入的相对路径。如果没有指定,sourcemaps文件不会生成。
[--targetBinaryVersion <targetBinaryVersion>] app的版本号,如果没有指定,默认使用Info.plist中的version值
[--rollout <rolloutPercentage>]
指定可以接收这次更新的用户百分比(在1-100的数字)如果没有设置这个参数,它会设置为100。
二复杂方式、生成bundle
发布更新之前,需要先把 js打包成 bundle,如:
第一步: 在 工程目录里面新增 bundles文件:mkdir bundles
第二步: 运行命令打包 react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试。
eg:
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --dev false
成功将返回:
Loading dependency graph, done.
bundle: Writing bundle output to: ./bundles/index.android.bundle
bundle: Done writing bundle output
Assets destination folder is not set, skipping...
需要注意的是:
忽略了资源输出是因为 输出资源文件后,会把bundle文件覆盖了。
输出的bundle文件名不叫其他,而是 index.android.bundle,是因为 在debug模式下,工程读取的bundle就是叫做 index.android.bundle。
平台可以选择 android 或者 ios。
发布更新
打包bundle结束后,就可以通过CodePush发布更新了。在终端输入
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境 --description: 更新描述 --mandatory: 是否强制更新
eg:
code-push release smallred ./bundles/index.android.bundle 1.1.3 --deploymentName Production --description "1.1.3支持文章缓存。" --mandatory true
code-push release smallred ./bundles/index.android.bundle 1.0.1 --deploymentName Staging --description "1.0.1支持文章缓存。" --mandatory true
成功将返回:
Successfully released an update containing the "./bundles/index.android.bundle" file to the "Production" deployment of the "smallred" app.
9、查看发布的历史记录
在终端输入 code-push deployment history <appName> Staging 可以看到Staging版本更新的时间、描述等等属性。
如eg:
code-push deployment history smallred Production
code-push deployment history smallred Staging
部署测试
在应用创建时,会自动生成Staging与Production这两个环境.
应用在开发阶段,通常都是在Staging下进行开发的,而Production作为生产环境.
当应用在开发阶段开发完毕,可使用code-push promote命令从Staging 迁移到Production中
CodePush简介
CodePush 是微软提供的一套提供给 React Native 和 Cordova 开发者,直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。
关于热更新
React Native 官方并没有提供热更新的技术方案,但是它是支持热更新的。
React Native 中的热更新有点像 App 的版本更新,也就是根据查询 server 端的版本和手机端目前 App 的版本进行对比,然后来执行是否更新的操作。
根本原因在于 React Native 的加载启动机制:React Native 会将一系列资源打包成js bundle文件,系统加载js bundle文件,解析并渲染。所以,React Native热更新的根本原理就是更换js bundle文件,并重新加载,新的内容就完美的展示出来了。
一。CodePush热更新组件详细接入教程《安装和RN集成》
1、安装 CodePush CLI
code-push register
这将会启动浏览器,要求验证Github或微软帐号。一旦验证成功,它将创建一个CodePush帐号跟你的Github或MSA相连,并生成一个访问密钥(Access Key),然后你可以拷贝/粘贴到CLI(它会提示你这样做)
如果没有自动打开浏览器,检查设置默认的浏览器
3、//热更新平台的账号信息
register info code-push for android
github username: xmfengwankeji
password: fengwan777
4、验证我的登录是否成功
$ code-push login
5、在CodePush服务器注册App(不同平台使用不同的名字)
添加Android平台应用;smallred是你app_name
code-push app add <appName> <os> <platform>
如:
$ code-push app add smallred Android react-native
│ Name │ Deployment Key │
│ Production │ FhW9iTw89LOuCywielf8Z9AV_8o-e4b0d9e2-373f-4966-a7e5-a158ec8b9b57 │
│ Staging │ ataVr8Yk2HYxxlS29OUm_SFejDxHe4b0d9e2-373f-4966-a7e5-a158ec8b9b57 │
1-如果你的App既有iOS又有Android,请为不同平台创建单独的App;
2-成功,会返回Deployment Key。
3-所有新的Apps自动会出现2个部署环境:staging代表开发版的热更新部署,用于测试更新;production代表生产版的。
4-在ios中,将staging的key复制在info.plist的CodePushDeploymentKey值中
在android中,复制在Application的getPackages的CodePush构造中。
ps:你可以通过code-push deployment ls <app_name> -k命令来查看deployment key。
我们可以输入如下命令来查看我们刚刚添加的App
$ code-push app list
二、RN代码中集成CodePush的SDK
1.在根目录(项目目录)执行安装集成的组件react-native-code-push
react-native link react-native-code-push
至此Code Push for Android的SDK已经集成完成。
2.在android中配置参数
在 android/app/build.gradle文件里面添如下代码:
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
然后在/android/settings.gradle中添加如下代码:
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
3.运行 code-push deployment -k ls <appName>获取 部署秘钥。默认的部署名是 staging,所以 部署秘钥(deployment key ) 就是 staging。
code-push deployment -k ls smallred
如果之前的都配置正确,那这里可以看到Production与Staging的Deployment Key,
将这两个key粘贴下来.如果环境来决定需要用到哪个key.
在刚开始,肯定需要测试,
那就将Staging对应的Deployment Key,替换到下面deployment-key-here的代码中.
地址:https://www.jianshu.com/p/87ccfb795635
4.添加配置。当APP启动时我们需要让app向CodePush咨询JS bundle的所在位置,这样CodePush就可以控制版本。更新 MainApplication.java文件:
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@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 "code-push deployment ls <appName> -k" to retrieve your key.
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new CodePush("ataVr8Yk2HYxxlS29OUm_SFejDxHe4b0d9e2-373f-4966-a7e5-a158ec8b9b57", MainApplication.this, BuildConfig.DEBUG),
//new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
关于deployment-key的设置
在上述代码中我们在创建CodePush实例的时候需要设置一个deployment-key,因为deployment-key分生产环境与测试环境两种,所以建议大家在build.gradle中进行设置。在build.gradle中的设置方法如下:
打开android/app/build.gradle文件,找到android { buildTypes {} }然后添加如下代码即可:
android {
...
buildTypes {
debug {
...
// CodePush updates should not be tested in Debug mode
...
}
releaseStaging {
...
buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'
...
}
release {
...
buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"'
...
}
}
...
}
心得:另外,我们也可以将deployment-key存放在local.properties中:
code_push_key_production=FhW9iTw89LOuCywielf8Z9AV_8o-e4b0d9e2-373f-4966-a7e5-a158ec8b9b57
code_push_key_staging=ataVr8Yk2HYxxlS29OUm_SFejDxHe4b0d9e2-373f-4966-a7e5-a158ec8b9b57
然后在就可以在android/app/build.gradle可以通过下面方式来引用它了:
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
android {
...
buildTypes {
debug {
...
// CodePush updates should not be tested in Debug mode
...
}
releaseStaging {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'
...
}
release {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'
...
}
}
...
}
在android/app/build.gradle设置好deployment-key之后呢,我们就可以这样使用了:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
...
new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line.
...
);
}
5.修改versionName。
在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。
android{
defaultConfig{
versionName "1.0.0"
}
}
详细的操作在官网demo示例中:
https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/App.js
三。配置Android平台《发布更新》
7、发布更新RN的bundle到微软服务器
CodePush支持两种发布更新的方式:
一是通过code-push release-react简化方式,
二是通过code-push release的复杂方式。
一简化方式、命令格式:
code-push release-react <appName> <platform>
如eg:
code-push release-react smallred ios
code-push release-react smallred android
code-push release-react smallred ios --t 1.0.0 --dev false --d Production --des "1.优化操作流程" --m true
code-push release-react smallred android --t 1.0.0 --dev false --d Production --des "1.优化操作流程" --m true
[--bundleName <bundleName>] 指明生成JS Bundle的文件名
[--deploymentName <deploymentName>] 部署环境名:Staging(临时环境)、Production(生产环境)
[--description <description>] 更新内容描述
[--development <development>] 指明是否要生成一个非最小化,开发的JS bundle文件。默认是false,禁用警告提示并且bundle文件是最小化的。
[--disabled <disabled>] 指明一个版本更新是否可以被用户下载。如果没有指定,版本更新是有效的(如:用户将要下载的那一刻你的应用称为同步
)。如果你想发布一个更新但不是立即生效,那么这个参数是有价值的,直到你明确用[补丁]发布,当你要让用户能够下载(如:公告博客上线)。
[--entryFile <entryFile>] 指明相对应用根目录的路径入口JavaScript 文件。
[--mandatory] 更新是否强制性(true、false)
[--sourcemapOutput <sourcemapOutput>] 指明生成的JS bundle 的sourcemap写入的相对路径。如果没有指定,sourcemaps文件不会生成。
[--targetBinaryVersion <targetBinaryVersion>] app的版本号,如果没有指定,默认使用Info.plist中的version值
[--rollout <rolloutPercentage>]
指定可以接收这次更新的用户百分比(在1-100的数字)如果没有设置这个参数,它会设置为100。
二复杂方式、生成bundle
发布更新之前,需要先把 js打包成 bundle,如:
第一步: 在 工程目录里面新增 bundles文件:mkdir bundles
第二步: 运行命令打包 react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试。
eg:
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --dev false
成功将返回:
Loading dependency graph, done.
bundle: Writing bundle output to: ./bundles/index.android.bundle
bundle: Done writing bundle output
Assets destination folder is not set, skipping...
需要注意的是:
忽略了资源输出是因为 输出资源文件后,会把bundle文件覆盖了。
输出的bundle文件名不叫其他,而是 index.android.bundle,是因为 在debug模式下,工程读取的bundle就是叫做 index.android.bundle。
平台可以选择 android 或者 ios。
发布更新
打包bundle结束后,就可以通过CodePush发布更新了。在终端输入
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境 --description: 更新描述 --mandatory: 是否强制更新
eg:
code-push release smallred ./bundles/index.android.bundle 1.1.3 --deploymentName Production --description "1.1.3支持文章缓存。" --mandatory true
code-push release smallred ./bundles/index.android.bundle 1.0.1 --deploymentName Staging --description "1.0.1支持文章缓存。" --mandatory true
成功将返回:
Successfully released an update containing the "./bundles/index.android.bundle" file to the "Production" deployment of the "smallred" app.
9、查看发布的历史记录
在终端输入 code-push deployment history <appName> Staging 可以看到Staging版本更新的时间、描述等等属性。
如eg:
code-push deployment history smallred Production
code-push deployment history smallred Staging
部署测试
在应用创建时,会自动生成Staging与Production这两个环境.
应用在开发阶段,通常都是在Staging下进行开发的,而Production作为生产环境.
当应用在开发阶段开发完毕,可使用code-push promote命令从Staging 迁移到Production中