2025 新版 RN 热更新(CodePush版)

前言

1、对于0 基础的同学建议

看下 19 年写的这篇会更详细点,本文不会特别细:code-push-server的私有化部署

2、首先要理解

app 库:提供打包命令,项目下载,项目更新

客户端 cli:文件上传 ,本身不打包,调用 app 的脚本打包。

服务器:文件派发,起到文件托管的作用。

备注:客户端cli 与服务端是配套的,他俩负责文件的派发,所以不管你 rn 项目版本怎么迭代,或者说用 weex、uniapp、h5 、windows项目,只要服务器能跑,只要你别动它,它都兼容。

3、我的配置:

app 库:“react-native-code-push”: “9.0.1”

热更项目:lisong/code-push-server

cli:code-push-cli@2.1.9

4、成果预

不重启、实时更新代码与资源演示
在这里插入图片描述

一、app 库

1、新建项目

下文所有的是基于你是新建的 rn 项目,如果是旧项目自行适配

# 已失效
react-native init demo --verbose --version 0.75.3
# 用这个
npx react-native init AwesomeProject --version 0.75.3

2、导库

所有的 code-push 客户端库都是 fork 微软的,这里直接上微软最新的

"react-native-code-push": "9.0.1"

app 库使用revopush 的也可以 (试过了没毛病):@revopush/react-native-code-push

"@revopush/react-native-code-push": "1.0.0"

3、android 配置

此处与旧版一致,没有什么改动。

当然你使用三方的 (如你自己 fork 的或者@revopush/react-native-code-push)记得对应导包目录改下即可。

  • build.gradle改动

不管使用哪个,最新版 Gradle 未及时适配,修改如下:

目录:node_module/react-native-code-push/android/build.gradle

apply plugin: "com.android.library"

def DEFAULT_COMPILE_SDK_VERSION = 26
def DEFAULT_BUILD_TOOLS_VERSION = "26.0.3"
def DEFAULT_TARGET_SDK_VERSION = 26
def DEFAULT_MIN_SDK_VERSION = 16

android {
    namespace "com.microsoft.codepush.react"

    compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
    buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : DEFAULT_MIN_SDK_VERSION
        targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION
        versionCode 1
        versionName "1.0"
    }

    lintOptions {
        abortOnError false
    }

    defaultConfig {
        consumerProguardFiles 'proguard-rules.pro'
    }
}

dependencies {
    implementation "com.facebook.react:react-native:+"
    implementation 'com.nimbusds:nimbus-jose-jwt:9.37.3'
}
  • MainApplication修改 JS 入口文件
import com.microsoft.codepush.react.CodePush
override fun getJSBundleFile(): String? {
    return CodePush.getJSBundleFile()
}
  • value/strings.xml 新增

这 2 个 key 是 react-naive-code-push/android 会自动从代码中读取,也可以通过 js CodePush.sync 传入

<string moduleConfig="true" name="CodePushDeploymentKey">wS0x2UeVrgtXk40D9J754knkNr254ksvOXqog</string>
<string moduleConfig="true" name="CodePushServerUrl">http://yourServerUrl:3000</string>
  • app/build.gradle
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle";

dependencies {
    implementation project(':react-native-code-push')
}
  • Setting.gradle
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

客户端的代码向来改动很频繁,后续维护如果对不上建议熟读源码(非常重要)或者看官方的各端集成方式

4、ios 配置

  • AppDelegate.m 改动

sourceURLForBridge 方法下return [self bundleURL];改成条件判断

#if DEBUG
  return [self bundleURL];
#else
  return [CodePush bundleURL];
#endif
  • CodePush.podspec改动

目录:node_module/react-native-code-push/CodePush.podspec

修改如下,注意此版本较低可以自行优化下配置:

require 'json'

package = JSON.parse(File.read(File.join(__dir__, 'package.json')))

Pod::Spec.new do |s|
  s.name           = 'CodePush'
  s.version        = package['version'].gsub(/v|-beta/, '')
  s.summary        = package['description']
  s.author         = package['author']
  s.license        = package['license']
  s.homepage       = package['homepage']
  s.source         = { :git => 'https://github.com/Microsoft/react-native-code-push.git', :tag => "v#{s.version}"}
  s.ios.deployment_target = '7.0'
  s.tvos.deployment_target = '9.0'
  s.preserve_paths = '*.js'
  s.library        = 'z'
  s.source_files = 'ios/CodePush/*.{h,m}'
  s.public_header_files = ['ios/CodePush/CodePush.h']

  # Note: Even though there are copy/pasted versions of some of these dependencies in the repo,
  # we explicitly let CocoaPods pull in the versions below so all dependencies are resolved and
  # linked properly at a parent workspace level.
  s.dependency 'React'
  s.dependency 'SSZipArchive', '~> 2.1'
  s.dependency 'JWT', '~> 3.0.0-beta.7'
  s.dependency 'Base64', '~> 1.1'
end
  • Info.plist

添加服务器地址配置

<key>CodePushDeploymentKey</key>
<string>Ej9L9PeVzEY29cu1GLzKXN5WjQt54ksvOXqog</string>
<key>CodePushServerURL</key>
<string>http://yourServelUrl:3000</string>

如果你的热更新是http,还需要将NSAllowsArbitraryLoads配置改为true,并且设置你的域名为例外

备注:此域名不用带端口号与http://

<dict>
	  <!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
		<key>NSAllowsArbitraryLoads</key>
		<true/>
		<key>NSExceptionDomains</key>
        <dict>
            <key>你的域名</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
	</dict>

5、RN 升级网址

此处与 code-push 无关,仅适用于你有 RN 版本改动需求:RN 升级对比

二、热更新服务器

1、为什么选 lisong 而非microsoft

通过下图可以看到lisong 的 start 还是远远高于 microsoft,这是因为 microsoft的并不支持开发者完全自由部署(依赖于微软的appcenter,当然现在不知道),lisong 是fork microsoft 的完善成开发者自由部署
在这里插入图片描述

mysql 下载官网

code-push-server

使用微软code push和私有化部署code-push-server的过程

2、mysql

  • mysq使用8.0以下版本

因为 8.0 mysql 使用了caching_sha2_password 插件,废弃了mysql_native_password,而 lisong 的服务代码使用的是旧版插件,否则你的mysql报错:Plugin ‘mysql_native_password’ is not loaded`

  • 旧版 mysql安装

如果你的服务器上已经存在高版本 mysql,建议通过 docker 安装

docker pull mysql:5.7.23

默认端口号是 3306,这里换成 3307,同时 code-push-server 中也要指向 3307 端口

添加初始化密码:新增容易环境变量,密码的字段是MYSQL_ROOT_PASSWORD
在这里插入图片描述

  • 如果你可以直接 3306 端口安装旧版mysql,修改密码
// 以管理员方式打开 mysql
mysql -u root -p
// mysql命令行中输入然后回车(注意 mysql的命令都是以分号;结尾)
ALTER USER 'root'@'localhost' IDENTIFIED BY '1234567890';
// 退出 mysql
exit;
  • 服务器进程常驻
nohup ./bin/www &!
回车
logout
  • 杀死常驻进程
// 模糊查找
ps -ef | grep www
kill -9 你的进程

更多命令参考:linux后台进程常驻

3、渐进式发布

微软的渐进式发布理念

1、发版流程:先打Staging 包 => 发灰度包=> 灰度包扩大比例 => Staging 包推送到Production

备注:不建议直接打Production 包,建议用验证好的包一步步推送到用户设备

2、紧急 bug 修复:可直接打Production 包

三、安装 Code Push CLI

新版 使用appcenter

1、登录不上

code-push cli 最新版修改了登录接口,导致无法登录 lisong 搭建的服务器,所以我们只能使用 2.1.9 版本

npm i code-push-cli@2.1.9 -g

2、app bundle打包失败

code-push cli@2.1.9 无法打包高版本 rn,因为 react-native 打包的 cli 改了

新版:/node_modules/react-native/cli.js

旧版:/node_modules/react-native/local-cli/cli.js,对应的cli.js 源码

'use strict';

var cli = require('@react-native-community/cli');

if (require.main === module) {
    cli.run();
}

module.exports = cli;

对此我们的解决方案有 3 种,都可以

1、改code-push-cli@2.1.9 源代码

这种我还没尝试,理论上没问题,因此第1种与第2种本质上是一个,就是让 cli 与 app 代码对上。

2、项目的react-native添加local-cli/cli.js

上文已经贴过代码了,亲自尝试无问题

3、cli 从code-push 换成code-push-standalone

打开微软的最新代码 main 分支code-push-server下的 cli 目录 ,按照提示走即可(亲自尝试无问题),

弊端:所有的 code-push 命令要换成code-push-standalone ,且部分命令有改动需要换一下,有一点适应成本
在这里插入图片描述

3、code push常用命令

// 账户相关
code-push login 登陆
code-push loout 注销
code-push register http://yourServerUrl:3000/ 注册
code-push whoami 查看当前会话登录账号信息
code-push access-key ls 列出登陆的token
code-push access-key rm <accessKye> 删除某个 access-key

// app操作相关
code-push app add <appName> <platform> react-native  在账号里面添加一个新的app
code-push app remove 或者 rm 在账号里移除一个 app
code-push app rename 重命名一个存在 app
code-push app list 或则 ls 列出账号下面的所有 app
code-push app transfer 把app的所有权转移到另外一个账号
code-push promote sunny635533/DigitalMine-Android Staging Production 推送到另一个部署环境

// 应用信息相关
code-push deployment add <appName> 部署
code-push deployment rm <appName> 删除部署
code-push deployment rename <appName> 重命名
code-push deployment ls <appName> 列出应用的部署情况
code-push deployment ls <appName> -k 查看部署的key
code-push deployment history <appName> <deploymentName> 查看历史版本
code-push deployment list rnDemo 查看密钥
 
// 发布
code-push release-react <appName> <platform> -t 版本  -d 环境  --des 描述 -m true (强制更新)
code-push promote <源部署名称> <目标部署名称> --rollout 20% //灰度
code-push rollout <部署名称> --disable //撤销灰度

// 清除历史部署记录
code-push deployment clear <appName> Production or Staging
 
// 回滚
code-push rollback <appName> Production --targetRelease v4(codepush服务部署的版本号)
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的所有权转移到另外一个账号
code-push app ls 查看已注册的应用
code-push deployment ls appName -k  查看应用key

code-push login 登陆 

code-push loout 注销

code-push access-key ls 列出登陆的token

code-push access-key rm <accessKye> 删除某个 access-key

code-push app add <appName> <platform> react-native  在账号里面添加一个新的app

code-push app remove 或者 rm 在账号里移除一个 app

code-push app rename 重命名一个存在 app

code-push app list 或则 ls 列出账号下面的所有 app

code-push app transfer 把app的所有权转移到另外一个账号

code-push deployment add <appName> 部署

code-push deployment rm <appName> 删除部署

code-push deployment rename <appName> 重命名

code-push deployment ls <appName> 列出应用的部署情况

code-push deployment ls <appName> -k 查看部署的key

code-push deployment history <appName> <deploymentName> 查看历史版本

code-push deployment clear <appName> Production or Staging  清除历史部署记录

code-push release-react <appName> <platform> -t 版本  -d 环境  --des 描述 -m true (强制更新)    发布

示例:

code-push release-react ReactNativeDemo android -m true -d Staging --des "test" -t "1.0.0"
code-push release-react ReactNativeDemoIos ios -m true -d Staging --des "test" -t "1.0.0"
code-push-standalone release-react ReactNativeDemo android -m true -d Staging --des "test" -t "1.0.0"

code-push release-react XMAndroid android -m true -d Staging --des "test" -t "2.3.953"

四、答疑

1、图片使用方式

正常使用 source 即可,src 是用在 uri 上的不要混淆,具体支持能力看 react-native-code-push文档

// 支持绝对路径方式
import test from "@assets/test.png"
// 支持相对路径方式
import test from "../../assets/test.png"

<Image source={test}/>

2、热更新下载是 diff还是整包

code-push-server 同时支持整包、diff 包,会按照一定命中算法下发。

3、第一次是否需要把未更新的jsbundle上报上去

需要,第一次热更新你需要把未更新的包和第一次更新的包都发上去,内部需要做 diff 命中

4、测试更新异常

注意项目的版本号要对得上,如果热更新的-t 版本号是 1.0.0 ,那么 app 的版本号也要是 1.0.0,不能写成 1.0

5、code-push更新后重新打开回退问题

如果没有调用 CodePush.sync 方法,则需要手动调用CodePush.notifyAppReady。

此外检查下你的原生 AppDelegate 页面 jsbundle 的加载是不是漏了使用 CodePush 的 bundle

return [CodePush bundleURL];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lkv9A73H-1587373233409)(/Users/hxl/Library/Application Support/typora-user-images/image-20200420162337555.png)]

参考:https://github.com/microsoft/react-native-code-push?tab=readme-ov-file

6、热更新应用上架应用市场

在这里插入图片描述
因此不存在热更新应用无法上架应用市场的说法,参考:链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流星雨在线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值