`
啸笑天
  • 浏览: 3436184 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

React Native CodePush 最新配置

阅读更多

 

原文地址:https://github.com/easyui/blog/blob/master/ReactNative/2017-09-04-React-Native-CodePush/2017-09-04-React-Native-CodePush.md

 

本文使用最新开发环境开发环境: OSX: 10.12.6 xcode:8.3.3 react native:0.47.0 codePush:^5.0.0-beta"

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

安装 CodePush CLI

  • 在终端输入 npm install -g code-push-cli,就可以安装了。
  • 安装完毕后,输入 code-push -v查看版本,如看到版本代表成功。(我安装的是2.0.2-beta)

注册CodePush账号  

  • 在终端输入code-push register,会在浏览器注册页面让你选择授权账号(我选择了github登录)。
  • 授权通过之后,CodePush会告诉你“access key”,复制此key到终端即可完成注册。
  • 然后终端输入code-push login进行登陆,登陆成功后,你的session文件将会写在 /Users/你的用户名/.code-push.config。

用户操作相关命令

  • 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> <os> <platform>即可完成注册。

示例:

  app add MyApp ios react-native      Adds app "MyApp", indicating that it's an iOS React Native app
  app add MyApp windows react-native  Adds app "MyApp", indicating that it's a Windows React Native app
  app add MyApp android cordova       Adds app "MyApp", indicating that it's an Android Cordova app

比如你执行code-push add demoapp ios react-native,注册完成之后会返回一套deployment key,该key在后面步骤中会用到:

在CodePush服务器注册app成功

https://mobile.azure.com/apps 也可以看到你注册的app:

网页查看

如果你的应用分为Android和iOS版,那么在向CodePush注册应用的时候需要注册两个App获取两套deployment key,app名字不能相同,所以可以选择-ios,-android区分。如:

code-push  add demoapp-ios ios react-native
code-push  add demoapp-android android react-native

app管理相关命令

  • 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

react native 集成CodePush模块:

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

执行成功后package.json文件中会添加了:

	"dependencies": {
		···
		"react-native-code-push": "^5.0.0-beta",
      ···
	},

iOS

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

运行 rnpm link react-native-code-push。这条命令将会自动帮我们在iOS(android)文件中添加好设置,同时更新了项目中的配置代码。(在React Native v0.27及以后版本RNPM已经被集成到了 React Native CL中,就不需要再进行安装了。)

其中iOS中的配置代码更新了AppDelegate.m文件:

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

在终端运行此命令之后,终端会提示让你输入ios和android的deployment key,可以不输入直接单击enter跳过,等会在项目中配置。

配置Deployment Key

  1. 选择Build Settings页签 ➜ 单击 + 按钮然后选择添加User-Defined Setting
  2. 然后输入CODEPUSH_KEY(名称可以自定义),设置2个deployment key

设置deploymentkey.png

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

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

至此,iOS的配置完成。

使用CodePush进行热更新

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

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

发布更新

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发布更新

需要先执行react-native bundle打包资源:

react-native bundle --entry-file index.ios.js --bundle-output ./bundles/main.jsbundle --platform ios --assets-dest ./bundles --dev false

bundle资源放入项目:

打包资源

bundle资源通过CodePush发布更新,在终端输入: code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境 --description: 更新描述 --mandatory: 是否强制更新

eg:
code-push release Demoapp ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章缓存。" --mandatory true

注意:

  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会拒绝此次更新。
  5. 在终端输入 code-push deployment history <appName> Staging 可以看到Staging版本更新的时间、描述等等属性。

部署APP相关命令

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

开发与测试

开发

上面提到rnpm link react-native-code-push执行往后,AppDelegate.m文件更新了:

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

下面更新js文件:

    ···
    constructor(props) {
        super(props);
        registerApp('wx94071fc9a6634781');
        const appId = 'qlJun5W9xYIdpi1nS8vepcDA-gzGzoHsz';
        const appKey = 'phlBacJt2JNSXW9RVuKl7KMQ';
        AV.init({ appId, appKey });

        ConfigManager.shareInstance().fetchAppConfig()

        CodePush.sync({
            deploymentKey: '12343kvGomTxA-AQtfd1234MxL12342eca8-90e6-428a-89ed-ba750111119f',
            updateDialog: null,
            installMode: CodePush.InstallMode.ON_NEXT_RESTART,
            mandatoryInstallMode: CodePush.InstallMode.ON_NEXT_RESTART,
        });

    }
    ···
    
    let codePushOptions = { checkFrequency: CodePush.CheckFrequency.MANUAL };
    App = CodePush(codePushOptions)(App);
    AppRegistry.registerComponent('miniDeer', () => App);

这段代码是每次启动app的时候检查更新和下载,如果有更新就下载好了,等下次启动的时候更新。具体js的代码可以参考https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/demo.js

调试

iOS

  1. iOS调试需要在AppDelegate.m中进行如下修改:
//#ifdef DEBUG
//    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
//#else
    jsCodeLocation = [CodePush bundleURL];
//#endif

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

不可以模拟器调试:

不可以模拟器调试

  1. 打包bundle,并且把bundle和assets放入项目:
$ react-native bundle --entry-file index.ios.js --bundle-output ./bundles/main.jsbundle --platform ios --assets-dest ./bundles --dev false
  1. 发布更新
$ code-push release demoApp ./bundles/ 1.0.0 --deploymentName Staging --description "修改了title" --mandatory true

  1. 发布成功后就可以启动项目测试,等更新成功后就杀掉app重新启动(不要用xcode run)

$ code-push deployment ls demoApp -k 可以查看刚才发布的记录

测试发布的JS发布到正式版

使用场景:当你在指定的部署环境下测试更新时,例如Staging,测试通过后,想把这个更新发布到正式生产环境Production中,则可以使用code-push promote MyAppAndroid Staging Production,这时可以修改一些元数据,例如--description、--targetBinaryVersion、--rollout等。

指令

code-push promote

–description, –des描述[string] [默认值: null]

–disabled, -x该促进更新,客户端是否可以获得更新[boolean] [默认值: null]

–mandatory, -m是否强制更新[boolean] [默认值:null]

–rollout, -r此促进更新推送用户的百分比[string] [默认值: null]

eg:

code-push promote MyAppStaging Production

"MyApp"中"Staging"部署的最新更新发布到"Production"部署中

code-push promote MyAppStaging Production –des "Production rollout" -r 25

"MyApp"中"Staging"部署的最新更新发布到"Production"部署中,并且只推送25%的用户

rollback回滚

使用场景:当你发布的更新测试没通过时,可以回滚到之前的某个版本。code-push rollback MyAppAndroid Production,当执行这个命令时它会在MyAppAndroid上的Production部署上再次发布一个release,这个release的代码和元属性与Production上倒数第二个版本一致。也可以通过可选参数--targetRelease来指定rollback到的版本,例如code-push rollback MyAppAndroid Production --targetRelase v2,则会新建一个release,这个release的代码和元属性与v2相同。

JavaScript API 简介

  • 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表现,不然直接用这个方法就可以了。
options参数是个字典

  • 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:
syncStatusChangeCallbac是监听更新状态变化的回调 downloadProgressCallback是下载更新包的回调

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. 有更新,但installModeInstallMode.ON_NEXT_SUSPEND,并且程序一直处于前台且活跃状体 。
  5. 自从上次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 当 调用 sync 或 LocalPackage.install 方法时,指定的 install mode是 ON_NEXT_RESTART 或 ON_NEXT_RESUME时 。 这两种情况都是当app重启或resume时,更新内容才能被看到。
  2. 在特定情况下,如用户从其它页面返回到APP的首页时,这个时候调用此方法完成过更新对用户来说不是特别的明显。因为强制重启,能马上显示更新内容。

参考

code-push 官网

code push cli手册

react-native-code-push github

react-native-code-push进阶篇

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

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Android代码-react-native-push-notification

    React Native Push Notifications React Native Local and Remote Notifications for iOS and Android Supported React Native Versions Component Version RN Versions README 1.0.7 = 2.1.0 &gt;= 0.33 ...

    React Native用Code Push 实现热更新

    简单的用code push实现React Native 热更新的例子。具体安装步骤可以参考React http://blog.csdn.net/u011886447/article/details/78715407 -- React Native用CodePush实现热更新(一) 和 ...

    React Native By Example

    React Native By Example by Richard Kho English | 24 Apr. 2017 | ASIN: B01M31KB4Q | 414 Pages | AZW3 | 4.46 MB Key Features Work on native APIs and UI Elements using React Native Get the best of both...

    React Native Debugger reactnative可视化调试工具

    mac端可视化调试react或者reactnative工具,可以调试redux应用状态

    React and React Native_Code 源码

    React and React Native_Code 源码 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    东方耀手把手教React Native实战开发

    第2课2、手把手教React Native实战之从React到RN 第3课3、手把手教React Native实战之flexbox布局(RN基础) 第4讲4、手把手教React Native实战之flexbox布局(伸缩属性) 第5讲5、手把手教React Native实战之盒子模型...

    react-native-code-push集成android篇.docx

    react-native-code-push集成android篇主要是讲述怎么在react-native中android端集成codepush热更新,内容详细,过程丰富,很适合新手,过程一目了然

    react-native-code-push集成之ios篇.docx

    react-native-code-push集成之ios篇是react-native IOS端集成codepush热更新的过程,内容丰富,过程详细,非常适合新手

    适用于 Android 和 iOS 的 React Native NFC 模块 react-native-nfc

    为 React Native 带来 NFC 功能。灵感来自phonegap-nfc和react-native-ble-manager 该库最简单(也是最常见)的用例是读取NFC包含 的标签NDEF,可以通过以下代码实现: import React from 'react'; import {View, ...

    React Native 开发指南

    本书通过丰富的示例和详细的讲解, 介绍了 React Native 这款 JavaScript 框架。 在 React Native 中利用现有的 JavaScript 和 React 知识,就可以开发和部署功能完备的、真正原生的移动应 用,并同时支持 iOS 与 ...

    react-native-viewpager-React Native版本的ViewPager控件,自动播放,无限循环。.zip

    React Native版本的ViewPager控件,自动播放,无限循环。项目地址:https://github.com/race604/react-native-viewpager 效果图:使用说明: 运行 npm 安装 react-native-viewpager --save代码如下:var ViewPager...

    React Native Cookbook [2016]

    Leverage the best of iOS and Android for React Native development while maximizing code reuse and cohesion Implement architecture patterns in your React Native application that support efficient data ...

    react native 实现水波纹效果

    react native 实现水波纹效果,效果非常棒哦

    reactnative显示本地图片

    react native 显示本地图片

    React and React Native [Kindle Edition]

    React and React Native by Adam Boduch English | 8 Mar. 2017 | ASIN: B01MQ1GHCS | 604 Pages | AZW3 | 7.22 MB Key Features Build React and React Native applications using familiar component concepts ...

    React Native in Action

    PART 1 Getting started with React Native Chapter 1. Getting Started With React Native Chapter 2. Understanding React Chapter 3. Building Your First React Native App PART 2 Developing applications in ...

    30天学习ReactNative教程

    30天学习React Native教程

    React and React Native

    Use React and React Native to build applications for desktop browsers, mobile browsers, and even as native mobile apps Build React and React Native applications using familiar component concepts Dive ...

    2019年最新英文版React Native in Action

    React Native apps compile into platform-specific code, reducing development time, effort, and cost! And because you’re using JavaScript and the React framework, you benefit from a huge ecosystem of ...

Global site tag (gtag.js) - Google Analytics