美文网首页react nativeReact Nativeios专题
React Native热更新部署/热更新-CodePush最

React Native热更新部署/热更新-CodePush最

作者: CrazyCodeBoy | 来源:发表于2016-07-23 13:44 被阅读26377次

    React Native应用部署/热更新-CodePush最新集成总结(新)

    本文出自《React Native学习笔记》系列文章。
    了解更多,可以关注我的GitHub和加入:
    React Native学习交流群

    React Native学习交流群React Native学习交流群

    更新说明:
    此次博文更新适配了最新版的CodePush v1.17.0;添加了iOS的集成方式与调试技巧;添加了更为简洁的CodePush发布更新的方式以及进行了一些其他的优化。

    React Native的出现为移动开发领域带来了两大革命性的创新:

    1. 整合了移动端APP的开发,不仅缩短了APP的开发时间,也提高了APP的开发效率。
    2. 为移动APP动态更新提供了基础。

    本文将向大家分享React Natvie应用部署/动态更新方面的内容。

    React Native支持大家用React Native技术开发APP,并打包生成一个APP。在动态更新方面React Native只是提供了动态更新的基础,对将应用部署到哪里,如何进行动态更新并没有支持的那么完善。好在微软开发了CodePush,填补React Native 应用在动态更新方面的空白。CodePush 是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务。下面将向大家分享如何使用CodePush实时更新你的应用,后期会分享不采用CodePush,如何自己去实现React Native应用热更新。

    CodePush简介

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

    CodePush 可以进行实时的推送代码更新:

    • 直接对用户部署代码更新
    • 管理 Alpha,Beta 和生产环境应用
    • 支持 React Native 和 Cordova
    • 支持JavaScript 文件与图片资源的更新

    CodePush开源了react-native版本,react-native-code-push托管在GitHub上。

    安装与注册CodePush

    使用CodePush之前首先要安装CodePush客户端。本文以OSX 10.11.5作为平台进行演示。

    安装 CodePush CLI

    管理 CodePush 账号需要通过 NodeJS-based CLI。
    只需要在终端输入 npm install -g code-push-cli,就可以安装了。
    安装完毕后,输入 code-push -v查看版本,如看到版本代表成功。
    ![安装 CodePush CLI成功](https://raw.githubusercontent.com/crazycodeboy/RNStudyNotes/master/React%20Native应用部署、热更新-CodePush最新集成总结/images/安装 CodePush CLI成功.png)
    目前我的版本是 1.12.1-beta

    PS.
    npm为NodeJS的包管理器,如果你没安装NodeJS请先安装。

    创建一个CodePush 账号

    在终端输入code-push register,会打开如下注册页面让你选择授权账号。

    注册codepush注册codepush
    授权通过之后,CodePush会告诉你“access key”,复制此key到终端即可完成注册。
    ![获取codepush access key](https://raw.githubusercontent.com/crazycodeboy/RNStudyNotes/master/React%20Native应用部署、热更新-CodePush最新集成总结/images/获取codepush access key.png)
    然后终端输入code-push login进行登陆,登陆成功后,你的session文件将会写在 /Users/你的用户名/.code-push.config。
    登陆成功登陆成功

    PS.相关命令

    • code-push login 登陆
    • code-push loout 注销
    • code-push access-key ls 列出登陆的token
    • code-push access-key rm <accessKye> 删除某个 access-key

    在CodePush服务器注册app

    为了让CodePush服务器知道你的app,我们需要向它注册app: 在终端输入code-push app add <appName>即可完成注册。

    code-push-add-appcode-push-add-app

    注册完成之后会返回一套deployment key,该key在后面步骤中会用到。

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

    code-push app add MyApp-Android
    code-push app add MyApp-iOS
    

    PS.相关命令

    • code-push app add 在账号里面添加一个新的app
    • code-push app remove 或者 rm 在账号里移除一个app
    • code-push app rename 重命名一个存在app
    • code-push app list 或则 ls 列出账号下面的所有app
    • code-push app transfer 把app的所有权转移到另外一个账号

    集成CodePush SDK

    Android

    下面我们通过如下步骤在Android项目中集成CodePush。
    第一步:在项目中安装 react-native-code-push插件,终端进入你的项目根目录然后运行
    npm install --save react-native-code-push

    第二步:在Android project中安装插件。
    CodePush提供了两种方式:RNPM 和 Manual,本次演示所使用的是RNPM。
    运行npm i -g rnpm,来安装RNPM。

    在React Native v0.27及以后版本RNPM已经被集成到了 React Native CL中,就不需要再进行安装了。

    第三步: 运行 rnpm link react-native-code-push。这条命令将会自动帮我们在anroid文件中添加好设置。

    react-native-code-push has been successfully linkedreact-native-code-push has been successfully linked

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

    第四步: 在 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')
    

    第五步: 运行 code-push deployment -k ls <appName>获取 部署秘钥。默认的部署名是 staging,所以 部署秘钥(deployment key ) 就是 staging。
    第六步: 添加配置。当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("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=erASzHa1-wTdODdPJDh6DBF2Jwo94JFH08Kvb
    code_push_key_staging=mQY75RkFbX6SiZU1kVT1II7OqWst4JFH08Kvb
    

    如图:


    local.properties存放codepush-keylocal.properties存放codepush-key

    然后在就可以在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.
             ...
         );
    }
    

    第七步:修改versionName。
    在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。

    android{
        defaultConfig{
            versionName "1.0.0"
        }
    }
    

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

    iOS

    CodePush官方提供RNPM、CocoaPods与手动三种在iOS项目中集成CodePush的方式,接下来我就以RNPM的方式来讲解一下如何在iOS项目中集成CodePush。

    第一步:在项目中安装react-native-code-push插件,终端进入你的项目根目录然后运行

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

    第二步: 运行 rnpm link react-native-code-push。这条命令将会自动帮我们在ios中添加好设置。

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

    关于deployment-key的设置

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

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

    Duplicate-Release-Staging.pngDuplicate-Release-Staging.png

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

    添加User-Defined-Setting添加User-Defined-Setting

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

    设置Staging deployment key设置Staging deployment key

    提示:你可以通过code-push deployment ls <APP_NAME> -k命令来查看deployment key。

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

    引用CODEPUSH_KEY引用CODEPUSH_KEY

    到目前为止,iOS的设置已经完成了,和在Android上的集成相比是不是简单了很多呢。

    使用CodePush进行热更新

    设置更新策略

    在使用CodePush更新你的应用之前需要,先配置一下更新控制策略,即:

    • 什么时候检查更新?(在APP启动的时候?在设置页面添加一个检查更新按钮?)
    • 什么时候可以更新,如何将更新呈现给终端用户?

    最简单的方式是在根component中进行上述策略控制。

    1. 在 js中加载 CodePush模块:
      import codePush from 'react-native-code-push'
      2.在 componentDidMount中调用 sync方法,后台请求更新
      codePush.sync()

    如果可以进行更新,CodePush会在后台静默地将更新下载到本地,等待APP下一次启动的时候应用更新,以确保用户看到的是最新版本。
    如果更新是强制性的,更新文件下载好之后会立即进行更新。
    如果你期望更及时的获得更新,可以在每次APP从后台进入前台的时候去主动的检查更新:
    在应用的根component的componentDidMount中添加如下代码:

    AppState.addEventListener("change", (newState) => {
        newState === "active" && codePush.sync();
    });
    

    发布更新

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

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

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

    命令格式:

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

    eg:

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

    再来个更高级的:

    code-push release-react MyApp-iOS ios  --t 1.0.0 --dev false --d Production --des "1.优化操作流程" --m true
    

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

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

    另外,我们可以通过code-push deployment ls <appName>来查看发布详情与此次更新的安装情况。

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

    code-push release发布更新呢我们首先需要将js与图片资源进行打包成 bundle。

    生成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.android.js --bundle-output ./bundles/index.android.bundle --dev false

    生成bundle生成bundle

    需要注意的是:

    • 忽略了资源输出是因为 输出资源文件后,会把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 GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章缓存。" --mandatory true

    推送更新到CodePush推送更新到CodePush

    注意:

    1. CodePush默认是更新 staging 环境的,如果是staging,则不需要填写 deploymentName。
    2. 如果有 mandatory 则Code Push会根据mandatory 是true或false来控制应用是否强制更新。默认情况下mandatory为false即不强制更新。
    3. 对应的应用版本(targetBinaryVersion)是指当前app的版本(对应build.gradle中设置的versionName "1.0.6"),也就是说此次更新的js/images对应的是app的那个版本。不要将其理解为这次js更新的版本。
      如客户端版本是 1.0.6,那么我们对1.0.6的客户端更新js/images,targetBinaryVersion填的就是1.0.6。
    4. 对于对某个应用版本进行多次更新的情况,CodePush会检查每次上传的 bundle,如果在该版本下如1.0.6已经存在与这次上传完全一样的bundle(对应一个版本有两个bundle的md5完全一样),那么CodePush会拒绝此次更新。
      如图:
      对应一个版本有两个bundle的md5完全一样对应一个版本有两个bundle的md5完全一样

    所以如果我们要对某一个应用版本进行多次更新,只需要上传与上次不同的bundle/images即可。如:
    eg:
    对1.0.6的版本进行第一次更新:
    code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章缓存。" --mandatory true
    对1.0.6的版本进行第二次更新:
    code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.新添加收藏功能。" --mandatory true

    1. 在终端输入 code-push deployment history <appName> Staging 可以看到Staging版本更新的时间、描述等等属性。
      eg:
      code-push release Equipment ./bundles 1.0.1

    下面我们启动事先安装好的应用,看有什么反应:

    提示更新提示更新
    应用启动之后,从CodePush服务器查询更新,并下载到本地,下载好之后,提示用户进行更新。这就是CodePush用于热更新的整个过程。

    更多部署APP相关命令

    • code-push deployment add <appName> 部署
    • code-push deployment rename <appName> 重命名
    • code-push deployment rm <appName> 删除部署
    • code-push deployment ls <appName> 列出应用的部署情况
    • code-push deployment ls <appName> -k 查看部署的key
    • code-push deployment history <appName> <deploymentNmae> 查看历史版本(Production 或者 Staging)

    调试技巧

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

    Android

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

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

    iOS

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

    导入bundle到xcode导入bundle到xcode

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

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

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

    JavaScript API Reference

    • allowRestart
    • checkForUpdate
    • disallowRestart
    • getUpdateMetadata
    • notifyAppReady
    • restartApp
    • sync

    其实我们可以将这些API分为两类,一类是自动模式,一类是手动模式。

    自动模式

    sync为自动模式,调用此方法CodePush会帮你完成一系列的操作。其它方法都是在手动模式下使用的。
    codePush.sync
    codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress)): Promise<Number>;
    通过调用该方法CodePush会帮我们自动完成检查更新,下载,安装等一系列操作。除非我们需要自定义UI表现,不然直接用这个方法就可以了。
    sync方法,提供了如下属性以允许你定制sync方法的默认行为

    • deploymentKey (String): 部署key,指定你要查询更新的部署秘钥,默认情况下该值来自于Info.plist(Ios)和MianActivity.java(Android)文件,你可以通过设置该属性来动态查询不同部署key下的更新。
    • installMode (codePush.InstallMode): 安装模式,用在向CodePush推送更新时没有设置强制更新(mandatory为true)的情况下,默认codePush.InstallMode.ON_NEXT_RESTART即下一次启动的时候安装。
    • mandatoryInstallMode (codePush.InstallMode):强制更新,默认codePush.InstallMode.IMMEDIATE。
    • minimumBackgroundDuration (Number):该属性用于指定app处于后台多少秒才进行重启已完成更新。默认为0。该属性只在installModeInstallMode.ON_NEXT_RESUME情况下有效。
    • updateDialog (UpdateDialogOptions) :可选的,更新的对话框,默认是null,包含以下属性
      • appendReleaseDescription (Boolean) - 是否显示更新description,默认false
      • descriptionPrefix (String) - 更新说明的前缀。 默认是” Description: “
      • mandatoryContinueButtonLabel (String) - 强制更新的按钮文字. 默认 to “Continue”.
      • mandatoryUpdateMessage (String) - 强制更新时,更新通知. Defaults to “An update is available that must be installed.”.
      • optionalIgnoreButtonLabel (String) - 非强制更新时,取消按钮文字. Defaults to “Ignore”.
      • optionalInstallButtonLabel (String) - 非强制更新时,确认文字. Defaults to “Install”.
      • optionalUpdateMessage (String) - 非强制更新时,更新通知. Defaults to “An update is available. Would you like to install it?”.
      • title (String) - 要显示的更新通知的标题. Defaults to “Update available”.

    eg:

    codePush.sync({
          updateDialog: {
            appendReleaseDescription: true,
            descriptionPrefix:'\n\n更新内容:\n',
            title:'更新',
            mandatoryUpdateMessage:'',
            mandatoryContinueButtonLabel:'更新',
          },
          mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
          deploymentKey: CODE_PUSH_PRODUCTION_KEY,
        });
    

    手动模式

    codePush.allowRestart

    codePush.allowRestart(): void;
    允许重新启动应用以完成更新。
    如果一个CodePush更新将要发生并且需要重启应用(e.g.设置了InstallMode.IMMEDIATE模式),但由于调用了disallowRestart方法而导致APP无法通过重启来完成更新,
    可以调用此方法来解除disallowRestart限制。
    但在如下四种情况下,CodePush将不会立即重启应用:

    1. 自上一次disallowRestart被调用,没有新的更新。
    2. 有更新,但installModeInstallMode.ON_NEXT_RESTART的情况下。
    3. 有更新,但installModeInstallMode.ON_NEXT_RESUME,并且程序一直处于前台,并没有从后台切换到前台的情况下。
    4. 自从上次disallowRestart被调用,没有再调用restartApp

    codePush.checkForUpdate

    codePush.checkForUpdate(deploymentKey: String = null): Promise<RemotePackage>;
    向CodePush服务器查询是否有更新。
    该方法返回Promise,有如下两种值:

    • null 没有更新
      通常有如下情况导致RemotePackage为null:

      1. 当前APP版本下没有部署新的更新版本。也就是说没有想CodePush服务器推送基于当前版本的有关更新。
      2. CodePush上的更新和用户当前所安装的APP版本不匹配。也就是说CodePush服务器上有更新,但该更新对应的APP版本和用户安装的当前版本不对应。
      3. 当前APP已将安装了最新的更新。
      4. 部署在CodePush上可用于当前APP版本的更新被标记成了不可用。
      5. 部署在CodePush上可用于当前APP版本的更新是"active rollout"状态,并且当前的设备不在有资格更新的百分比的设备之内。
    • A RemotePackage instance
      有更新可供下载。

    eg:

    codePush.checkForUpdate()
    .then((update) => {
        if (!update) {
            console.log("The app is up to date!");
        } else {
            console.log("An update is available! Should we download it?");
        }
    });  
    

    codePush.disallowRestart

    codePush.disallowRestart(): void;
    不允许立即重启用于以完成更新。
    eg:

    class OnboardingProcess extends Component {
        ...
    
        componentWillMount() {
            // Ensure that any CodePush updates which are
            // synchronized in the background can't trigger
            // a restart while this component is mounted.
            codePush.disallowRestart();
        }
    
        componentWillUnmount() {
            // Reallow restarts, and optionally trigger
            // a restart if one was currently pending.
            codePush.allowRestart();
        }
    
        ...
    }
    

    codePush.getUpdateMetadata
    codePush.getUpdateMetadata(updateState: UpdateState = UpdateState.RUNNING): Promise<LocalPackage>;
    获取当前已安装更新的元数据(描述、安装时间、大小等)。
    eg:

    // Check if there is currently a CodePush update running, and if
    // so, register it with the HockeyApp SDK (https://github.com/slowpath/react-native-hockeyapp)
    // so that crash reports will correctly display the JS bundle version the user was running.
    codePush.getUpdateMetadata().then((update) => {
        if (update) {
            hockeyApp.addMetadata({ CodePushRelease: update.label });
        }
    });
    
    // Check to see if there is still an update pending.
    codePush.getUpdateMetadata(UpdateState.PENDING).then((update) => {
        if (update) {
            // There's a pending update, do we want to force a restart?
        }
    });
    

    codePush.notifyAppReady
    codePush.notifyAppReady(): Promise<void>;
    通知CodePush,一个更新安装好了。当你检查并安装更新,(比如没有使用sync方法去handle的时候),这个方法必须被调用。否则CodePush会认为update失败,并rollback当前版本,在app重启时。
    当使用sync方法时,不需要调用本方法,因为sync会自动调用。

    codePush.restartApp
    codePush.restartApp(onlyIfUpdateIsPending: Boolean = false): void;
    立即重启app。
    当以下情况时,这个方式是很有用的:

    1. app 当 调用 syncLocalPackage.install 方法时,指定的 install modeON_NEXT_RESTARTON_NEXT_RESUME时 。 这两种情况都是当app重启或resume时,更新内容才能被看到。
    2. 在特定情况下,如用户从其它页面返回到APP的首页时,这个时候调用此方法完成过更新对用户来说不是特别的明显。因为强制重启,能马上显示更新内容。

    总结

    上文已经介绍了CodePush在动态更新方面的一些特性,但CodePush也存在着一些缺点:

    1. 服务器在国外,在国内访问,网速不是很理想。
    2. 其升级服务器端程序并不开源的,后期微软会不会对其收费还是个未知数。
      如果在没有更好的动态更新React Native应用的方案的情况下,并且这些问题还在你的接受范围之内的话,那么CodePush可以作为动态更新React Native应用的一种选择。
      后期会向大家分享不采用CodePush,自己搭建服务器并实现React Native应用的动态更新相关的方案。

    参考:
    http://microsoft.github.io/code-push/docs/getting-started.html
    https://github.com/Microsoft/react-native-code-push

    相关文章

      网友评论

      • _Jason___:大佬,我再原生项目里面,用cocoapod加入的codepush,做热更新,没法实现热更新,到底是哪里不对,大佬有没有配置文档呢?在线等,急,Thanks♪(・ω・)ノ
      • JsLin_:按照你的ios配置: Build Settings页签 ➜ 单击 + 按钮然后选择添加User-Defined Setting

        然后在Info.plist文件,在CodePushDeploymentKey列的Value中输入$(CODEPUSH_KEY)
        更新不起作用 在Info.plist 中把key写死 却可以 不知道 什么原因?
        JsLin_:@giants_one code push版本号,要对应RN的版本,不然的话,很可能出现回滚,目前的话我这边不用archive 。我在项目中也是写死的,不过这样也好控制,生产替换生产的key开发换开发的key 更新的话根据版本号进行更新,最重要的是根据版本号控制。根据版本号,根据版本号。
        giants_one:我发现问题了,操作步骤:
        1,集成了code-push环境后,先Archive后导出包安装到手机上。
        2,修改js部分代码。
        3,code-push release-react RNApp ios --t 1.0.0 --dev false --d Production --des "1.测试" --m true
        4,代码上传完毕打开app,就可以了。
        注:一定要在Archive之后做js修改,否则你会发现安装到手机上到app已经是最新到版本了
        giants_one:我也是这样的情况,我试了很多次不管Staging还是Production,只要写死就有效,配置$(CODEPUSH_KEY)就没有效果,你解决了吗?
      • 魅璃儿:Update is invalid - A JS bundle file named "main.jsbundle" could not be found within the downloaded contents. Please ensure that your app is syncing with the correct deployment and that you are releasing your CodePush updates using the exact same JS bundle file name that was shipped with your app's binary.
        请问这个错误是什么原因导致的?怎么解决?
      • 魅璃儿:第五步: 运行 code-push deployment -k ls <appName>获取 部署秘钥。默认的部署名是 staging,所以 部署秘钥(deployment key ) 就是 staging。

        这位兄弟,这个写的有点模糊啊,都不知道你想说什么?
      • scue:CodePush的iOS模拟器调用技巧不错哟~
        scue:RN 0.48之后不会自动在模拟器上产生BUNDLE文件,需要修改一下配置:

        Build Pharses → Bundle React Native code and images
        ```
        export NODE_BINARY=node
        export FORCE_BUNDLING=true
        ../node_modules/react-native/scripts/react-native-xcode.sh
        ```

        添加了一行:`export FORCE_BUNDLING=true`
      • 还没想到叫什么:明明已经更新成功了,但是为什么应用还是没有改过来呢
      • 还没想到叫什么:已经提示我更新成功了,但是重新启动应用为啥没有弹框提示呢
        Successfully released an update containing
      • 还没想到叫什么:Successfully released an update containing the "./bundles/index.ios.bundle" file to the "Production" deployment of the "LoanmonProject-ios" app.
        已经成功了,但是重新启动程序并没有提示更新的弹框
      • Hero_trz:code-push loout 注销 你搞错了吧 应该是code-push logout
      • bb27bf1cf514: @Override
        protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG),
        );
        }
        };
        f8e5107ee6c8:@丶散华礼弥 你弄好了吗?
        我也遇到这问题了
        bb27bf1cf514:然后其他地方的配置使用rpm link 自动配置好了,,,就这些然后react-native run-android打包就报错了,,怎么回事??
      • bb27bf1cf514: buildTypes {

        debug {
        // CodePush updates should not be tested in Debug mode
        }

        releaseStaging {
        buildConfigField "String", "CODEPUSH_KEY", '"CblRTcXgh3XW09jdCVeosswTgvkJ8592e9f7-8a0e-430e-9567-61b17317f552"'
        }

        release {
        minifyEnabled enableProguardInReleaseBuilds
        proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        buildConfigField "String", "CODEPUSH_KEY", '"qzyGpt8t689VU_NGnZu2gyYJ5cYK8592e9f7-8a0e-430e-9567-61b17317f552"'
        }
        }
      • bb27bf1cf514:楼主,照你的配置,,打包时候 JSBundleLoader
        位置: 程序包 com.facebook.react.bridge
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:103: 错误: 找不到符号
        JSBundleLoader latestJSBundleLoader;
        ^
        符号: 类 JSBundleLoader
        位置: 类 CodePushNativeModule
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:105: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createAssetLoader(getReactApplicationContext(), latestJSBundleFile, false);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:107: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        注: D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java使用了未经检查或不安全的操作。
        注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
        4 个错误
        :react-native-code-push:compileDebugJavaWithJavac FAILED
      • bb27bf1cf514:之前配置好了codepush热更新,后面又加了第三方库,codepush不能更新新加的库,但是我不小心就就加了,然后就一直更新失败,该怎么解决?
      • 6b422c056b76:作者您好,我在下载完之后,配置好后运行react-native run-android 提示
        F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:14: 错误: 找不到符号
        import com.facebook.react.bridge.JSBundleLoader;
        ^
        符号: 类 JSBundleLoader
        位置: 程序包 com.facebook.react.bridge
        F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePush.java:21: 错误: CodePush不是抽象的, 并且未覆盖ReactPackage中的抽 象方法createJSModules()
        public class CodePush implements ReactPackage {
        ^
        F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:103: 错误: 找不到符号
        JSBundleLoader latestJSBundleLoader;
        ^
        符号: 类 JSBundleLoader
        位置: 类 CodePushNativeModule
        F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:105: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createAssetLoader(getReactApplicationContext(), latestJSBundleFile, false);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:107: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        注: F:\rn_test\new\apollo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java使用了未经检查或不安全的操作。
        注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
        5 个错误
        :react-native-code-push:compileReleaseJavaWithJavac FAILED


        怎么弄一下了
        bb27bf1cf514:port com.facebook.react.bridge.JSBundleLoader;
        ^
        符号: 类 JSBundleLoader
        位置: 程序包 com.facebook.react.bridge
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:103: 错误: 找不到符号
        JSBundleLoader latestJSBundleLoader;
        ^
        符号: 类 JSBundleLoader
        位置: 类 CodePushNativeModule
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:105: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createAssetLoader(getReactApplicationContext(), latestJSBundleFile, false);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java:107: 错误: 找不到符号
        latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
        ^
        符号: 变量 JSBundleLoader
        位置: 类 CodePushNativeModule
        注: D:\WebstormProjects\company\updateDemo\node_modules\react-native-code-push\android\app\src\main\java\com\microsoft\codepush\react\CodePushNativeModule.java使用了未经检查或不安全的操作。
        注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
        4 个错误
        :react-native-code-push:compileDebugJavaWithJavac FAILED
        怎么回事??
        江湖人称向前兄:你好,请问你是如何解决的?
      • 90b2cdbcc6ad:大神好,我在配置android的时候,new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG)这里的CODEPUSH_KEY取不到咋回事啊,buildConfigField ("String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'),buildConfigField ("String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'),这两块已经加上了,请问是什么原因。
      • 宇宙只有巴掌大:我测试使用Staging 的key 可以更新,但是如果我用./gradlew assembleRelease 打包apk 并且把key 全都改成 Production 的key后 更新就无效了是怎么回事?打包发布用的是:code-push release-react MyApp android --t 1.0.0 --d Production --des "1.优化操作流程" --m true 测试用的:code-push release-react <appName> <platform>
        张自恒:同问,请问楼上两位大神解决了吗~
        fozero:@宇宙只有巴掌大 同问, 使用Staging 的key可以更新, 换成Production 的key就不行了 ,不知道为啥。
        宇宙只有巴掌大:我替换了 android 里面的 key 和 reactjs 里面的 key 都替换了,。code-push deployment ls <appName> -k 查看的时候 也是发布成功了,但是 却是0更新
      • 47fe3088500c:大神好腻害 惊叹... 请问有关于原生Android app中嵌入RN 进行热更新的一些分享吗?多谢大神
        kala888:问一个问题,github上报了一个bug
        https://github.com/Microsoft/react-native-code-push/issues/909
      • 3ec06068fa83:原生应用中嵌入RN能不能使用CodePush呢,有没有有经验的小伙伴,这个文档步骤好像是对纯RN应用的
        3ec06068fa83:谢谢谢谢,大神QQ我加你了,加下我,文中还有个地方code-push deployment -k ls <appName>这个命令运行错误,-k好像应该放在后面,你看下,这样code-push deployment ls <appName> -k
        CrazyCodeBoy:@Neo_4411 可以的,原生应用中嵌入RN使用CodePush,可参考:http://coding.imooc.com/learn/questiondetail/11254.html
      • 43ec5675ebd2:1. releaseStaging {
        ...
        buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'
        ...
        }

        release {
        ...
        buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'
        ...
        此处的"code_push_key_production"和"code_push_key_staging"写反了。
        2.new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG)的不识别。
        CrazyCodeBoy:@Neo_4411 可以的,原生应用中嵌入RN使用CodePush,可参考:http://coding.imooc.com/learn/questiondetail/11254.html
        3ec06068fa83:原生应用中嵌入RN能不能使用CodePush呢,有没有有经验的小伙伴,这个文档步骤好像是对纯RN应用的
        43ec5675ebd2:2.需要在 debug {
        buildConfigField "boolean", "LOG_DEBUG", "true"
        // CodePush updates should not be tested in Debug mode
        buildConfigField "String", "CODEPUSH_KEY", properties.getProperty("code_push_key_staging")=>加上
        }
      • 2285bc549482:android 在 downloading package,下载这个提示后,一会就crash了。完全不知道是什么回事,哪位大大遇到过?谢谢!
      • 楚怀哲:code-push release-react zyxcp android
      • WatsonGo:楼主在iOS下又遇到过下面的错误吗?
        Update is invalid - A JS bundle file named "bundle/main.jsbundle" could not be found within the downloaded contents. Please ensure that your app is syncing with the correct deployment and that you are releasing your CodePush updates using the exact same JS bundle file name that was shipped with your app's binary.
      • uncleRX:正式环境下 Xcode里面的环境 改release还是 staging
      • immutable:CodePush坑得很, 长城宽带的网络根本访问不了 :smile:
        d7441c20e1fd:@immutable 自建服务 https://github.com/lisong/code-push-server
        CrazyCodeBoy: @immutable 😂

      本文标题: React Native热更新部署/热更新-CodePush最

      本文链接:https://www.haomeiwen.com/subject/qwhwjttx.html