ReactNative CodePush热更新

CodePush简介

CodePush 是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务。CodePush 是提供给 React Native 和 Cordova 开发者直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。


CodePush安装与注册

1.安装 CodePush CLI

终端输入命令安装

npm install -g code-push-cli

2.注册CodePush 账号

在终端输入命令,会打开如下注册页面让你选择授权账号

code-push register

在这个网页可以选择Github。或者微软作为授权提供者,不过我觉得90%的开发者都会选择Github。

授权通过之后,CodePush会告诉你“access key”,复制此key到终端即可完成注册。然后终端输入code-push login进行登陆,登陆成功后,你的session文件将会写在 /Users/你的用户名/.code-push.config。只要不主动退出(通过code-push logout命令),登陆状态会一直有效。


在CodePush服务器注册app

在终端输入命令即可完成创建,注册完成之后会返回一套deployment key,包括Staging和Production。该key在后面步骤中会用到。

code-push app add <appName> <os> <platform>

如果你的应用分为Android和iOS版,那么在向CodePush注册应用的时候需要注册两个App获取两套deployment key

code-push app add tolvgxAD android react-native
code-push app add tolvgxIOS ios react-native

ps.相关命令

查看所有app:code-push app ls
新建app:code-push app add <appName> <os> <platform>
重命名app:code-push app rename <appName> <newAppName>
移除app:code-push app rm <appName>

CodePush集成

这里分Android集成和iOS集成,二者共同的部分如下:

1.首先,在RN项目中安装codePush依赖

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

2.运行命令自动构建关联

rnpm link react-native-code-push

在终端运行此命令之后,终端会提示让你输入deployment key,这是你只需将你的deployment Staging key输入进去即可,如果不输入则直接单击enter跳过分别在Android和IOS项目中进行配置。

Android

运行自动构建关联命令一般在Android项目中不会完全成功,如果不成功,参考下面的手动配置。

1.在android/app/build.gradle文件里面添如下代码:

apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"  

2.在/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.关于deployment-key的设置

打开android/app/build.gradle文件,修改android-buildTypes节点成如下:

 buildTypes {
    debug{
        //省略了其他配置
        // CodePush updates should not be tested in Debug mode
    }
    releaseStaging {
        buildConfigField "String", "CODEPUSH_KEY", '"此处填写Staging key"'
    }
    release {
        //省略了其他配置
        buildConfigField "String", "CODEPUSH_KEY", '"此处填写Production key"'
    }
}

4.配置CodePush类

当APP或者RN类启动时我们需要让app向CodePush咨询JS bundle的所在位置,这样CodePush就可以控制版本

这里分两种情况(不清楚的可以参考我的博客《ReactNative集成到现有原生应用&和完整RN项目的异同》):

(1)纯RN项目

在MainApplication中

@Override
protected String getJSBundleFile() {
    return CodePush.getJSBundleFile();
}
@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
       new MainReactPackage(),
       new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG)
  );
}

(2)现有项目嵌入RN

在单独的RN类ReactNativeActivity中,1.将CodePush作为扩展加入Packages 2.将.setBundleAssetName("index.android.bundle")替换为.setJSBundleFile(CodePush.getJSBundleFile()),如图:

List<ReactPackage> reactPackages = Arrays.<ReactPackage>asList(
        new MainReactPackage(),//默认
        new LinearGradientPackage(),//引入Rn渐变控件
        new CodePush(BuildConfig.CODEPUSH_KEY, ReactNativeActivity.this, BuildConfig.DEBUG),//codePush热更新
        new TransMissonPackage()//通信
);

mReactInstanceManager = ReactInstanceManager.builder()
        .setApplication(getApplication())
        .setJSMainModulePath("index")// ! 注意这里的index指向入口的js文件
//                .setBundleAssetName("index.android.bundle")
        .setJSBundleFile(CodePush.getJSBundleFile())// ! 此处为codePush加载JsBundle方式,默认为.setBundleAssetName("index.android.bundle")
//                .addPackage(new MainReactPackage())
        .addPackages(reactPackages)// ! 此处为扩展Packages,默认为.addPackage(new MainReactPackage())
        .setUseDeveloperSupport(BuildConfig.DEBUG)
        .setInitialLifecycleState(LifecycleState.RESUMED)
        .build();

5.关于VersionName

在 android/app/build.gradle中有个android.defaultConfig.versionName属性,我们需要把应用版本改成三位,比如1.0需要修改成1.0.0,codepush需要三位数

至此Code Push for Android的SDK已经集成完成。

IOS

关于deployment-key的配置

在我们想CodePush注册App的时候,CodePush会给我们两个deployment-key分别是在生产环境与测试环境时使用的,我们可以通过如下步骤来设置deployment-key。

1.用Xcode 打开项目 ➜ Xcode的项目导航视图中的PROJECT下选择你的项目 ➜ 选择Info页签 ➜ 在Configurations节点下单击 + 按钮 ➜ 选择Duplicate "Release ➜ 输入Staging(名称可以自定义);

2.然后选择Build Settings页签 ➜ 单击 + 按钮然后选择添加User-Defined Setting

3.然后输入CODEPUSH_KEY(名称可以自定义)

4.打开 Info.plist文件,在CodePushDeploymentKey列的Value中输入$(CODEPUSH_KEY)

至此Code Push for IOS的SDK已经集成完成。


使用CodePush进行热更新

设置更新策略

一般常见的应用内更新时机分为两种,一种是打开APP就检查更新,一种是放在设置界面让用户主动检查更新并安装。

1.在 js中加载 CodePush模块:

import codePush from 'react-native-code-push'

2.在 componentDidMount中调用 sync方法,后台请求更新

codePush.sync()

如果有更新包可供下载则会在重启后生效。不过这种下载和安装都是静默的,即用户不可见。如果需要用户可见则需要额外的配置,如下:

componentDidMount(){
    codePush.sync(
        {
            updateDialog: {
                appendReleaseDescription: true,
                title:'更新提示',
                descriptionPrefix:'',
                mandatoryUpdateMessage:'',
                mandatoryContinueButtonLabel:'立即更新',
                optionalUpdateMessage:'',
                optionalIgnoreButtonLabel: '稍后更新',
                optionalInstallButtonLabel: '立即更新',
            },
            installMode: codePush.InstallMode.IMMEDIATE,//ON_NEXT_RESTART,ON_NEXT_RESUME
            deploymentKey: CODE_PUSH_DEBUG_KEY,
        },
        (status)=>{
            switch (status) {
                case codePush.SyncStatus.DOWNLOADING_PACKAGE:
                    this.refs.toast.show('资源加载中...', 2000);
                    break;
                case codePush.SyncStatus.INSTALLING_UPDATE:
                    console.log(" INSTALLING_UPDATE");
                    break;
            }
        }
    );
}

发布更新

CodePush支持两种发布更新的方式,一种是通过code-push release-react简化方式,另外一种是通过code-push release的复杂方式。

方式一:通过code-push release-react发布更新

这种方式将打包与发布两个命令合二为一,可以说大大简化了我们的操作流程,建议大家多使用这种方式来发布更新。

命令格式:

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

示例:

code-push release-react tolvgxAD android --t 4.2.0 --dev false --d Staging --des "1.测试快捷发布 \n 2.优化操作流程" --m false

其中参数--t为二进制(.ipa与apk)安装包的的版本;--dev为是否启用开发者模式(默认为false);--d是要发布更新的环境分Production与Staging(默认为Staging);--des为更新说明;--m 是强制更新。

关于code-push release-react更多可选的参数,可以在终端输入code-push release-react进行查看。

方式二:通过code-push release发布更新

(1)手动执行打包Bundle命令打包

命令格式:

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

示例:

react-native bundle --platform android --entry-file index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --assets-dest ./android/app/src/main/res --dev false

(2)发布更新

命令格式:

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

示例:

code-push release tolvgxAD ./android/app/src/main/assets/index.android.bundle 4.2.0 --deploymentName Staging --description "4.测试ReactNative功能" --mandatory true

注意:对于对某个应用版本进行多次更新的情况,CodePush会检查每次上传的 bundle,如果在该版本下如1.0.6已经存在与这次上传完全一样的bundle(对应一个版本有两个bundle的md5完全一样),那么CodePush会拒绝此次更新。所以如果我们要对某一个应用版本进行多次更新,只需要上传与上次不同的bundle/images即可。

ps.相关命令

1、查看app的全部部署:code-push deployment ls <appName>
                code-push deployment ls tolvgxAD
2、查看app的某个部署的发布更新的历史记录:code-push deployment history <appName> <deploymentName> (一旦发布过更新就禁用:清除历史记录客户端加载的也是最后一次服务器bundle)
                code-push deployment history tolvgxAD Staging
3、清除与部署相关的发布历史记录:code-push deployment clear <appName> <deploymentName>

4、删除app的某个部署:code-push deployment remove <appName> <deploymentName>   (禁用:整个Production删除了,重新add后key就变了)
5、添加app的某个部署:code-push deployment add <appName> <deploymentName>
6、查看部署的key:code-push deployment ls <appName> -k 

使用rollback回滚

1、code-push rollback tolvgxAD Staging
      当执行这个命令时它会在tolvgxAD上的Staging部署上再次发布一个release,这个release的代码和元属性与Staging上倒数第二个版本一致。
2、code-push rollback tolvgxAD Staging --targetRelease v4
      当执行这个命令时它会在tolvgxAD上的Staging部署上再次发布一个release,这个release的代码和元属性与Staging上v4版本一致。
注意:这个回滚是主动回滚,与自动回滚不一样


添加合作者

一个App通常不会是一个人开发,因此codePush添加合作者是很常见的。通过 code-push collaborator来操作合作者相关命令。

Usage: code-push collaborator <command>
命令:
	  add     对指定的项目添加一个新的合作者
	  remove  删除指定的项目中的合作者
	  rm      删除指定的项目中的合作者
	  list    列出指定项目中的所有合作者
	  ls      列出指定项目中的所有合作者
示例:
code-push collaborator add AppDemo foo@bar.com 添加一个合作者foo@bar.com到AppDemo这个App中

调试技巧

如果你用模拟器进行调试CodePush,在默认情况下是无法达到调试效果的,因为在开发环境下装在模拟器上的React Native应用每次启动时都会从NodeJS服务器上获取最新的bundle,所以还没等CodePush从服务器将更新包下载下来时,APP就已经从NodeJS服务器完成了更新。

Android

为规避这个问题在Android可以将开发环境的调试地址改为一个不可用的地址,如下图:

这样APP就无法连接到NodeJS服务器了,自然也就不能从NodeJS服务器下载bundle进行更新了,它也只能乖乖的等待从CodePush服务器下载更新包进行更新了。

IOS

在iOS中我们需要上文中讲到的生成bundle,将bundle包与相应的图片资源拖到iOS项目中如图:

然后呢,我们需要在AppDelegate.m中进行如下修改:

//#ifdef DEBUG
//    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
//#else
    jsCodeLocation = [CodePush bundleURL];
//#endif

让React Native通过CodePush去获取bundle包即可。


总结

至此,我们已经介绍了CodePush在动态更新方面的一些特性,但CodePush也存在着一些缺点:服务器在国外,在国内访问,网速不是很理想。如果在没有更好的动态更新React Native应用的方案的情况下,并且这些问题还在你的接受范围之内的话,那么CodePush可以作为动态更新React Native应用的一种选择。

 

 

 

展开阅读全文

没有更多推荐了,返回首页