使用 CodePush 热更新 React Native 项目

最近在 React Native 项目部署了 CodePush 来做热更新,查了网上很多资料发现大多中文资料都比较陈旧了,打算更新一篇2017年末的CodePush 该如何使用。
CodePush的英文文档非常详细,英文不错的同学和详细信息可以直接去Github查看。
这篇简述使用 CodePush 的流程,翻译了 IOS、Android 原生代码的配置文档。

What is CodePush

React Native 应用程序的主要组成是 JavaScript 文件和附属的图片资源。然后由 packager 将它们和特定平台程序打包成二进制文件(.ipa.apk)。

CodePush 相当于一个中心仓库,将 JavaScript 文件和图像资源打包上传到CodePush服务器。由App程序在设置的时间获取服务器上更新的数据、执行更新。

通过CodePush,在 JavaScript 层面上的改动可以快速升级迭代,无需重新发布到App Store、Google Play 等应用商店。

安装 CodePush CLI

CodePush CLI 是用于上传、发布包到CodePush服务器的终端工具,同时也提供方便的功能执行打包命令。

关于CodePush CLI 官方有完善的中文文档,这里列出注册流程和一些常用的命令。

注册流程:

// 安装
npm install -g code-push-cli
// 验证安装成功
code-push -v 
// 注册CodePush账号
code-push register
// 登录
code-push login
// 在CodePush服务器注册 App,这里建议注册 appname-ios、appName-android 两个app
code-push app add <appName>

相关命令:

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

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

查看应用deployment key

code-push deployment ls <appName> -k
deployment key

CodePush中,每个app 默认有两个 deployment key,App使用不同的Key,可以取到不同key上的包。一般使用 Staging 作为测试使用,Production 用来发布生产。

deployment key 写在原生代码中,用来作为服务器获取更新的标志。可以通过配置打不同的包使用不同的key(后面会说到)。

在项目中安装 CodePush

安装 react-native-code-push

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

link react-native-code-push

// React Native 版本 >= v0.27
react-native link react-native-code-push

同时配置了 IOS、Android

IOS 配置 deployment key

deployment key 可以在Info.plist中直接设置,但是为了方便测试,添加一个打包配置用于区分Staging和Production是非常有用的。

  1. 打开你的 Xcode 项目,并在Project Navigator 窗口中选择你的项目

  2. 确保选择了PROJECT节点,而不是其中一个TARGETS

  3. 选择 Info 标签

  4. 单击Configurations部分中的+按钮,然后选择复制Release配置
    [图片上传失败...(image-342ce-1513212533873)]

  5. 重命名这个配置为Staging(或者任何你喜欢的)

  6. 选择Build Settings标签

  7. 找到 Build Location -> Per-configuration Build Products Path -> Staging 把 Staging 的值修改为$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)(之前是$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME))

[图片上传失败...(image-a01dbf-1513212533873)]

  1. 点击工具栏上的+按钮,然后选择Add User-Defined Setting
    [图片上传失败...(image-66a0b5-1513212533874)]

  2. 将这个新设置命名为CODEPUSH_KEY,将其展开,并为发布配置指定Staging配置的Stagingdeployment key和Productiondeployment key。
    [图片上传失败...(image-af21f3-1513212533874)]
    deployment key可以通过 code-push deployment ls <APP_NAME> -k获取

  3. 打开项目的Info.plist文件并将CodePushDeploymentKey条目的值更改为$(CODEPUSH_KEY)
    [图片上传失败...(image-66df04-1513212533874)]

现在,当运行或构建应用程序时,Staging 版本将自动配置为与 Staging 部署同步,并且发布版本将配置为与Production 部署同步。

Android 配置 deployment key

同样根据步骤:

  1. 打开app的build.gradle,(在React Native 项目目录下 android/app/build.gradle)
  2. 找到android { buildTypes {} }部分,并为调试版本和发布版本类型定义buildConfigField条目,分别引用StagingProduction部署密钥(deployment key)。
android {
  ...
  buildTypes {
      debug {
          ...
          // Note: CodePush updates should not be tested in Debug mode as they are overriden by the RN packager. However, because CodePush checks for updates in all modes, we must supply a key.
          buildConfigField "String", "CODEPUSH_KEY", '""'
          ...
      }

      releaseStaging {
          ...
          buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'
          ...
      }

      release {
          ...
          buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"'
          ...
      }
  }
  ...
}
  1. 将部署密钥通过您刚刚定义的构建配置传递给CodePush构造函数,而不是字符串文字。
    打开 MainApplication.java,做如下修改
// React Native >= v0.29
@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      ...
      new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line.
      ...
  );
}

现在,当运行或构建应用程序时,ReleaseStaging版本将自动配置为与Staging部署同步,并且Release版本将配置为与Production部署同步。

App 查询更新

在原生代码部署完成后,唯一需要确定的是App需要在何时与CodePush通信,获取更新。最简单的方法就是通过在包裹根组件的方式:

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

class MyApp extends Component {
}

export default codePush(MyApp);

还可以根据需要配置查询更新频率:

let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };

class MyApp extends Component {
}

export default codePush(codePushOptions)(MyApp);

也可以手动查询,例如:

let codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };

class MyApp extends Component {
    onButtonPress() {
        codePush.sync({
            updateDialog: true,
            installMode: codePush.InstallMode.IMMEDIATE
        });
    }

    render() {
        return (
            <View>
                <TouchableOpacity onPress={this.onButtonPress}>
                    <Text>Check for updates</Text>
                </TouchableOpacity>
            </View> 
        )
    }
}

export default codePush(codePushOptions)(MyApp);

部署

上传到 CodePush

在项目目录执行

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

默认发布到Staging,使用-d 选择deployment

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

注意:这里版本号使用的是现在原生项目中的版本号,也可以指定版本号

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

版本号可以使用范围表达式。

这部分有详细的中文文档:参考链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容