本文由我们团队的丁武龙组内分享总结
前言
随着 react-native 的出现, 让移动开发出现了更加便捷的方式, 由于 react-native 使用的是脚本语言编写, 实现了解释运行 https://baike.baidu.com/item/解释执行/8081777 的方式, 这种执行方式只需要替换脚本文件就可以了, 不需要再次发布应用程序, 极大的节省了发布时间和方便了迭代开发, 本文主要讲述的热更新组件是国内开发的组件 pushy, 其功能类似于 CodePush, 但由于 codePush 是国外的, 在国内访问的速度比较慢, pushy 支持增量更新, 最大化的降低更新的数据量, 节约流量.
操作流程
1. 要想使用 pushy, 那就先创建一个 RN 项目, 终端输入
react-native init projectName --version 0.55.4 // 指定 0.55.4 版本
2. 安装 update 工具, 因为 pushy 热更新需要 uodate 配合使用
npm install -g react-native-update-cli // 每台电脑只需要运行一次即可
3. 安装 pushy 组件, 这里使用的是 yarn 方式, 也可以使用 npm 方式
- //yarn 方式
- yarn add react-native-update
- //npm 方式
- npm install react-native-update --save
- //link 到项目中
- react-native link react-native-update
配置 Bundle URL
在 iOS 工程目录下, 首先在工程 target 的 Build Phases->Link Binary with Libraries 中加入 libz.tbd,libbz2.1.0.tbd
2. 然后再 AppDelegate.m 文件下添加以下代码
... 省略代码
- #import "RCTHotUpdate.h"
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- NSURL *jsCodeLocation;
- #if DEBUG
- jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
- #else
- // 非 DEBUG 情况下启用热更新
- jsCodeLocation=[RCTHotUpdate bundleURL];
- #endif
- ......
- }
3.iOS 外的白名单配置
从 iOS9 开始, 苹果要求以白名单的形式在 Info.plist 中列出外部的非 https 接口, 以督促开发者部署 https 协议. 在我们的服务部署 https 协议之前, 请在 Info.plist 中添加如下例外
4. 登录与创建应用
1. 首先需要在 http://update.reactnative.cn 注册一个账号, 然后 cd 到项目根目录下, 执行命令
pushy login
email: <注册邮箱>
password: <密码>
执行完了之后会在项目根目录下自动生成一个. update 文件, 注 (不要把这个文件上传到 Git 等 CVS 系统上. 你可以在. gitignore 末尾增加一行. update 来忽略这个文件) 登录完成之后即可创建安卓或者 ios 应用程序(每个账号不超过 3 个应用), 两端程序需要分别创建
- //ios
- pushy createApp --platform ios
App Name: <输入应用名字>
- //an
- pushy createApp --platform android
App Name: <输入应用名字>
创建完应用之后, 即可在项目里看到 update.json 文件, 内容形式如下
- {
- "ios": {
- "appId": 14954,
- "appKey": "OEKJy0mUCcbaFR9UJrMFrEOH-k89FX44"
- }
- }
可以把 update.json 上传到 Git 等 CVS 系统上, 与你的团队共享这个文件, 它不包含任何敏感信息. 当然, 他们在使用任何功能之前, 都必须首先输入 pushy login 进行登录.
以上步骤完成之后, 现在下面给给项目添加热更新功能代码
热更新功能实现
获取 Appkey
检查更新是必须提供 appkey, 创建应用的时候都会生成一个 appkey, 这个值保存在 update.json 文件中, 可以在 App.js 文件获取 appkey
- import {Platform,} from 'react-native';
- import updateConfig from './update.json';
- const {appKey} = updateConfig[Platform.OS];
检查更新 / 下载更新内容
使用异步函数 checkUpdate 可以检测当前版本是否需要更新
- checkUpdate(appKey)
- .then(info => {
- })
返回的 info 有一下几类情况
1.{expired: true}: 该应用包 (原生部分) 已过期, 需要去应用市场下载更新应用程序
2.{upToDate: true} 当前版本已经是最新版本, 无需更新
3.{update: true} 表示有新的版本可以更新了. info 的 name,description 字段可 以用于提示用户, 而 metaInfo 字段则可以根据你的需求自定义其它属性(如是否静默更新, 是否强制更新等等). 另外还有几个字段, 包含了完整更新包或补丁包的下载地址, react-native-update 会首先尝试耗费流量更少的更新方式. 将 info 对象传递给 downloadUpdate 作为参数即可.
切换版本
downloadUpdate 返回的是一个 hash 字符串, 是当前版本的唯一字符串.
可以使用 switchVersion 函数来快速切换版本, 应用程序会立即加载, 代码如下
- import React, {Component} from 'react'
- import {
- Platform,
- View,
- Alert,
- } from 'react-native'
- import {
- isFirstTime,
- isRolledBack,
- checkUpdate,
- downloadUpdate,
- switchVersion,
- switchVersionLater,
- markSuccess,
- } from 'react-native-update'
- ...
- componentWillMount() {
- if (isFirstTime) {
- Alert.alert('提示', '这是当前版本第一次启动, 是否要模拟启动失败? 失败将回滚到上一版本', [
- {text: '是', onPress: () => { throw new Error('模拟启动失败, 请重启应用') }},
- {text: '否', onPress: () => { markSuccess() }},
- ])
- } else if (isRolledBack) {
- Alert.alert('提示', '刚刚更新失败了, 版本被回滚.')
- }
- this.checkUpdate()
- }
- ...
- doUpdate = (info) => {
- downloadUpdate(info).then((hash) => {
- Alert.alert('提示', '下载完毕, 是否重启应用?', [
- {text: '是', onPress: () => { switchVersion(hash) }},
- {text: '否'},
- {text: '下次启动时', onPress: () => { switchVersionLater(hash) }},
- ])
- }).catch((err) => {
- Alert.alert('提示', '更新失败.')
- })
- };
- checkUpdate = () => {
- checkUpdate(appKey).then((info) => {
- // alert(info.upToDate)
- if (info.expired) {
- Alert.alert('提示', '您的应用版本已更新, 请前往应用商店下载新的版本', [
- {text: '确定', onPress: () => {}},
- ])
- } else if (info.upToDate) {
- Alert.alert('提示', '您的应用版本已是最新.')
- } else {
Alert.alert('提示', ` 检查到新的版本 ${info.name}, 是否下载?\n${info.description}`, [
- {text: '是', onPress: () => { this.doUpdate(info) }},
- {text: '否'},
- ])
- }
- }).catch((err) => {
- Alert.alert('提示', '更新失败.')
- })
- }
- ...
现在可以通过 update 服务检查版本是否有更新了,
发布应用包和版本
注意 从发布版本到正式上线期间, 不要更改脚本文件和资源, 如果修改, 可能会造成脚本出现问题, 导致无法更新.
1. 在真机模式或者 Generic iOS Device 模式下对项目打包, Product-Archive, 打包完成之后, 生成一个 IPA 文件, 上传到分发平台进行下载测试, 执行命令
pushy uploadIpa ipa 路径
发布热更新包
修改一行代码(比如在 App.js 文件增加一个弹框), 然后生成新的热更新版本.
- pushy bundle --platform ios Bundling with React Native version: 0.55.4
- .....
- Would you like to publish it?(Y/N)
如果想要立即发布, 输入 Y 即可,
- Uploading [========================================================] 100% 0.0s
- Enter version name: 1.100
- Enter description: update
- Enter meta info: {"ok":1}
- Version published: 42053
- Would you like to bind packages to this version?(Y/N)
此时版本已经提交到 update 服务, 但用户暂时看不到此更新, 你需要先将特定的包版本绑定到此热更新版本上
输入 Y 进行绑定
- Y
- 21144(出现的这串数字要记住, 下面要用到)) 1.1(normal) (newest)
- Total 1 packages.
- Enter packageId: 21144
- Ok.
至此, 热更新集成完成,
来源: https://juejin.im/entry/5b7a83da6fb9a019e52e6df4