React Native 热更新 CodePush
什么是 CodePush 与热更新
CodePush 是微软提供的一项云服务,专门为 React Native 和 Cordova 应用提供热更新能力。它允许开发者直接向用户终端推送 JavaScript 资源包、图片等静态资源的更新,而无需经过应用商店的漫长审核周期,从而快速修复缺陷或发布新功能。
热更新仅适用于 JavaScript 代码、资源文件(图片、字体等)和部分原生模块 的更新。对于原生代码(如 Java/Kotlin、Objective-C/Swift)的变动、新增原生模块依赖、NATIVE_BUILD 环境的改动,仍需要重新打包并通过应用商店发布新版本。
核心优点:
- 绕过应用商店审核,分钟级到达用户
- 可选强制更新或静默下载
- 支持灰度发布、回滚
环境准备与账号配置
安装 App Center CLI
CodePush 现在已经集成到 App Center 中,管理命令通过 appcenter-cli 执行。
npm install -g appcenter-cli
注册并创建应用
- 访问 App Center 注册账号(支持 GitHub、Microsoft 等登录)。
- 登录 CLI:
appcenter login - 在 App Center 中创建一个新的应用(Add new app),选择 OS: Android/iOS,Platform: React Native。
- 创建后复制应用密钥(App Secret),后续在终端需要用到。也可以创建两个应用分别对应 Android 和 iOS,方便独立管理版本。
在 React Native 项目中集成 CodePush
安装 SDK
npm install --save react-native-code-push
cd ios && pod install && cd ..
对于 React Native 0.60 及以上版本,自动链接已经完成。如果自动链接失败,可手动链接:
react-native link react-native-code-push
Android 平台配置
-
在
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') -
在
android/app/build.gradle中确保引入了依赖。 -
在
MainApplication.java(或MainApplication.kt)中注册 CodePush 的ReactNativeHost:@Override protected String getJSBundleFile() { return CodePush.getJSBundleFile(); }同时在
getPackages中加入new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG)。 -
在
android/app/src/main/res/values/strings.xml中添加 deployment key:<string moduleConfig="true" name="reactNativeCodePush_androidDeploymentKey">YOUR_ANDROID_DEPLOYMENT_KEY</string>Deployment Key 可以在 App Center 中对应应用的 “CodePush” 栏目下获取(Production/Staging 环境各有一个 key)。
iOS 平台配置
-
在
ios/你的项目名/Info.plist中添加CodePushDeploymentKey,值填写 iOS 应用的 deployment key。<key>CodePushDeploymentKey</key> <string>YOUR_IOS_DEPLOYMENT_KEY</string> -
将 App Center 的 URL 配置添加到
Info.plist(可选,用于自定义服务器):<key>CodePushServerURL</key> <string>https://codepush.appcenter.ms/</string> -
在
AppDelegate.m(或AppDelegate.mm)中更新 source URL:#import <CodePush/CodePush.h> ... - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [CodePush bundleURL]; #endif }
封装更新策略与 UI 提示
在 App.js(或入口文件)中包裹根组件,并配置更新检查逻辑。
import React, { useEffect } from 'react';
import codePush from 'react-native-code-push';
let codePushOptions = {
checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
installMode: codePush.InstallMode.ON_NEXT_RESUME,
mandatoryInstallMode: codePush.InstallMode.IMMEDIATE,
updateDialog: {
title: "发现新版本",
optionalUpdateMessage: "有新版本可用,是否立即更新?",
optionalInstallButtonLabel: "立即更新",
optionalIgnoreButtonLabel: "稍后",
mandatoryUpdateMessage: "必须更新才能继续使用",
mandatoryContinueButtonLabel: "更新",
},
};
function App() {
useEffect(() => {
codePush.sync({
updateDialog: true, // 显示默认对话框
installMode: codePush.InstallMode.IMMEDIATE, // 立即安装
});
}, []);
return <RootComponent />;
}
export default codePush(codePushOptions)(App);
常用参数说明:
checkFrequency:ON_APP_START应用启动时检查,ON_APP_RESUME从后台恢复时检查。installMode:IMMEDIATE立即安装(需重启应用),ON_NEXT_RESUME下次从后台切回时安装,ON_NEXT_RESTART下次冷启动时安装。mandatoryInstallMode: 当发布标记为强制更新时的安装策略。updateDialog: 自定义更新提示框内容。
发布 CodePush 更新
对项目完成修改并测试后,打包 bundle 并发布。
一、打包 JS bundle 和资源文件:
npx react-native bundle \
--platform android \ # 或 ios
--entry-file index.js \
--bundle-output ./release.bundle \
--dev false \
--assets-dest ./release
二、使用 App Center CLI 发布:
appcenter codepush release-react \
-a <owner>/<app-name> \
-d Production \ # 或 Staging
-t ">=1.0.0" \ # 目标二进制版本范围
--description "修复了某个bug"
-a参数格式为用户名/应用名,可在 App Center 应用总览页找到。-d指定部署环境,常用Staging(测试)和Production(生产)。-t规定此次更新适用的原生 app 版本范围,例如1.0.0表示只针对该版本,>=1.0.0表示1.0.0及以上版本。
发布成功后,已集成的终端将在下次触发检查时下载并安装更新。
多环境管理
建议创建至少两个 deployment:
- Staging:用于内部测试,在发布到正式环境前验证更新。
- Production:面向最终用户。
获取不同环境的 deployment key,并在构建不同环境的原生包时使用对应 key。例如,Android 可以在 buildTypes 中动态替换 key:
buildTypes {
debug {
buildConfigField "String", "CODEPUSH_KEY", '"STAGING_KEY"'
}
release {
buildConfigField "String", "CODEPUSH_KEY", '"PRODUCTION_KEY"'
}
}
版本控制与高级特性
控制目标二进制版本
发布时可通过 -t 参数精确控制更新送达的 native 版本。支持 semver range 语法:
1.0.0仅1.0.0>=1.0.0 <2.0.0全部1.x版本*所有版本
发布后可在 App Center 后台查看每个更新的安装指标。
强制更新
当发布紧急修复时,可标记为 mandatory:
appcenter codepush release-react ... --mandatory true
终端在同步时会采用 mandatoryInstallMode 指定的安装行为(通常为立即安装)。客户端 sync 时可配合自定义 UI 阻止用户继续使用。
回滚与历史记录
- 回滚:通过 CLI 或后台将某个部署环境回滚到上一版本:
appcenter codepush rollback -a <owner>/<app> -d Production - 查看历史:
appcenter codepush deployment history -a <owner>/<app> -d Staging
灰度与启动图兼容
对于包含启动页(splash screen)资源的应用,更新后如果资源有变,可能需要冷重启才能看到效果。建议代码中监听更新安装状态,在合适时机提示用户重启,或使用 restartApp 方法。
codePush.sync({
installMode: codePush.InstallMode.IMMEDIATE,
},
(status) => {
// 可以通过status监听状态变化
});
常见问题与排查
-
更新下载后未生效
检查installMode配置。若为ON_NEXT_RESUME,需将应用切到后台再回来才会安装。也可以使用codePush.restartApp()强制重启。 -
iOS 热更新闪退
确保在发布时没有改变原生桥接(native module)调用,或者页面引用了新的原生组件。这类修改必须通过 App Store 发布。 -
Android release build 不请求更新
确认strings.xml中 deployment key 正确且getJSBundleFile已重写。检查 proguard 规则是否保留了com.microsoft.codepush.react相关类。 -
更新包下载失败
国内网络可能受限,可考虑私有化部署 CodePush Server(参考 code-push-server 开源项目),然后修改CodePushServerURL。 -
命令行提示未登录
执行appcenter logout后重新appcenter login。
通过合理运用 CodePush,你的 React Native 应用将获得敏捷的迭代能力,在紧急修复和体验优化上抢占先机。