@hxa-rn/react-native-code-push
v1.0.0
Published
React Native plugin for the CodePush service
Readme
bravemobile-react-native-code-push
本项目基于 Soomgo-Mobile/react-native-code-push 开发。如果在使用过程中有任何问题,可以在 GitCode 提交 Issue,会及时跟进。
项目介绍
bravemobile-react-native-code-push(npm 发布版本 1.0.0,上游基线 12.4.0)是面向 HarmonyOS/OpenHarmony React Native 工程的自托管热更新库,适用于需要在运行期下发 RN JS Bundle、样式、文案和随包资源的业务场景。
鸿蒙适配 npm 包名为 @hxa-rn/react-native-code-push;其 HAR 内部 ohpm 模块名保持 @oh-rn/react-native-code-push。JS/TS 使用者仍通过 @bravemobile/react-native-code-push 导入。调用方通过 codePush 高阶组件、sync、checkForUpdate、RemotePackage.download、LocalPackage.install 与宿主侧 CodePushJSBundleProvider 完成更新检查、下载、安装、生效和回滚闭环。
核心能力包括:
- 自托管发布历史读取:由业务方实现
releaseHistoryFetcher,库侧负责版本、灰度、强制更新和失败包过滤。 - 更新包下载与校验:支持完整包和差分包下载、解压、合并、SHA-256 完整性校验和本地元数据落盘。
- 多种生效策略:支持立即生效、下次启动生效、回到前台生效和进入后台后生效。
- 状态与进度回调:提供同步状态、下载进度、版本不匹配、更新成功、回滚和异常回调。
- 宿主换包接线:通过
CodePushJSBundleProvider让 RN 实例优先加载沙箱更新包,并在无可用更新时回落内置 bundle。
集成指南
1. 安装 JS 依赖
宿主 React Native 工程安装 npmjs 上的精确版本:
npm install @hxa-rn/[email protected] --save-exact --legacy-peer-deps安装后宿主 package.json 中的依赖应为:
{
"dependencies": {
"@hxa-rn/react-native-code-push": "1.0.0"
}
}安装后本包位于 node_modules/@hxa-rn/react-native-code-push/,发布包已经包含 harmony/dist/code_push.har。RNOH 0.72.143 的自动链接需要真实目录形态的 node_modules;如果使用 pnpm,请执行 pnpm install --node-linker=hoisted,避免普通 pnpm 符号链接导致 linked 0 libraries。JS 侧仍按原库名导入 @bravemobile/react-native-code-push,由 npm 包 package.json 中的 harmony.alias 映射到鸿蒙适配包。
2. 生成鸿蒙侧 JS Bundle
以下命令必须在宿主 React Native 工程根目录执行(该目录应包含业务侧 index.js;不要在本仓库目录执行)。命令中的 harmony/entry/... 是宿主工程的入口模块路径,不是本仓库的 harmony/code_push/ HAR 模块路径。
当前交付默认只生成并加载 bundle.harmony.js,不要求预编译 Hermes HBC。
cd <宿主RN工程根目录>
# 生成宿主工程使用的 JS bundle
npx react-native bundle-harmony --dev false \
--bundle-output harmony/entry/src/main/resources/rawfile/bundle.harmony.js@hxa-rn/react-native-code-push 是 npm 安装包,@oh-rn/react-native-code-push 是 HAR 的 ohpm 模块名,JS 业务代码继续使用 @bravemobile/react-native-code-push。如果宿主工程没有自动生成鸿蒙原生侧依赖,按下面步骤手动接入。
如果宿主明确启用 Hermes HBC,需要按宿主 RNOH 工具链另行生成 hermes_bundle.hbc;该文件不是本库当前交付和默认编译的必需品。
3. 接入鸿蒙原生模块(手动链接)
在宿主鸿蒙工程的 harmony/oh-package.json5(需要落到与 OH_MODULES_DIR 一致的 harmony/oh_modules)中加入:
{
dependencies: {
"@oh-rn/react-native-code-push": "file:../node_modules/@hxa-rn/react-native-code-push/harmony/dist/code_push.har",
},
overrides: {
// 必须与宿主 RNOH har 保持一致:覆盖 code_push.har 内部指向
// RN 线安全扫描处置场景使用源码版 RNOH HAR,并在构建前执行 libevent 2.1.13 补丁脚本
"@rnoh/react-native-openharmony": "file:../node_modules/@react-native-oh/react-native-harmony/react_native_openharmony.har",
},
}如果宿主工程模板要求 harmony/entry/oh-package.json5 显式声明,也可在该文件中使用同一 HAR 路径;两处路径需保持一致。
cd <宿主RN工程根目录>\harmony
ohpm install如果 ohpm install --all 长时间无输出,可用 ohpm install --all --fetch_timeout 10000 --retry_times 0 --log_level debug 观察依赖解析进度;Windows 路径较长时,RNOH source-mode 构建建议在真实短路径工程目录中执行。
4. 注册 RNPackage(ETS)
在 entry/src/main/ets/RNPackagesFactory.ets 中加入本库的 Package:
import type { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
import { createRNOHPackages as createRNOHPackagesAutolinking } from './RNOHPackagesFactory';
import CodePushPackage from '@oh-rn/react-native-code-push';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
...createRNOHPackagesAutolinking(ctx),
new CodePushPackage(ctx),
];
}5. 接入 Bundle Provider(换包入口)
在宿主 EntryAbility 或承载 RNApp 的 ArkTS 页面中接入 CodePushJSBundleProvider,让运行期优先加载 CodePush 已下载的更新包,未命中时回退到应用内置 bundle:
import {
AnyJSBundleProvider,
ResourceJSBundleProvider,
RNApp,
} from '@rnoh/react-native-openharmony';
import { CodePushJSBundleProvider } from '@oh-rn/react-native-code-push';
const jsBundleProvider = new CodePushJSBundleProvider(
this.rnohCoreContext!.uiAbilityContext,
new AnyJSBundleProvider([
new ResourceJSBundleProvider(this.rnohCoreContext!.uiAbilityContext.resourceManager, 'bundle.harmony.js'),
]),
'bundle.harmony.js',
);
RNApp({
rnInstanceConfig: { createRNPackages },
appKey: 'YourApp',
jsBundleProvider,
});接入后即可在 JS/TS 代码中按原库名导入:
import codePush from '@bravemobile/react-native-code-push';6. 检查鸿蒙 SDK 版本
code_push.har 面向 RNOH 工程使用。确认宿主 harmony/build-profile.json5 的 runtimeOS 为 HarmonyOS,并保证 compatibleSdkVersion、targetSdkVersion 与宿主 RNOH 版本要求一致;示例工程当前使用 compatibleSdkVersion 5.0.1(13)、targetSdkVersion 6.1.0(23)。
7. 编译、安装、启动
# DevEco Studio 打开 harmony/ 工程,等待后台任务完成
# File > Project Structure > Signing Configs 勾选自动签名
# 选 entry 运行配置,连接设备,Debug/Run
# 或命令行:
cd <宿主RN工程根目录>\harmony
hvigorw --mode module -p module=entry@default -p product=default -p buildMode=release assembleHap
# 产物:harmony/entry/build/default/outputs/default/entry-default-signed.hap
# 装机与启动(真机已连接,hdc 可见设备):
hdc file send entry-default-signed.hap /data/local/tmp/entry.hap
hdc shell bm install -p /data/local/tmp/entry.hap
hdc shell aa start -a EntryAbility -b <你的 bundleName> # 见 AppScope/app.json5使用说明
接入 CodePush 高阶组件
import codePush from '@bravemobile/react-native-code-push';
const codePushOptions = {
checkFrequency: codePush.CheckFrequency.ON_APP_START,
installMode: codePush.InstallMode.ON_NEXT_RESTART,
releaseHistoryFetcher: async (request) => {
const response = await fetch(`https://your-server.example.com/releases/${request.app_version}.json`);
return await response.json();
},
onUpdateSuccess: (label) => {
console.info('CodePush updated:', label);
},
onUpdateRollback: (label) => {
console.info('CodePush rollback:', label);
}
};
function App() {
return <Root />;
}
export default codePush(codePushOptions)(App);手动检查、下载与安装
const remotePackage = await codePush.checkForUpdate();
if (remotePackage) {
const localPackage = await remotePackage.download((progress) => {
console.info(`${progress.receivedBytes}/${progress.totalBytes}`);
});
await localPackage.install(codePush.InstallMode.IMMEDIATE);
await codePush.notifyAppReady();
}一站式同步
const status = await codePush.sync(
{
installMode: codePush.InstallMode.ON_NEXT_RESTART,
mandatoryInstallMode: codePush.InstallMode.IMMEDIATE,
ignoreFailedUpdates: true
},
(syncStatus) => {
console.info('CodePush status:', syncStatus);
},
(progress) => {
console.info('CodePush progress:', progress.receivedBytes, progress.totalBytes);
}
);接入鸿蒙 bundle provider
import {
AnyJSBundleProvider,
ResourceJSBundleProvider,
RNApp
} from '@rnoh/react-native-openharmony';
import { CodePushJSBundleProvider } from '@oh-rn/react-native-code-push';
const jsBundleProvider = new CodePushJSBundleProvider(
this.rnohCoreContext!.uiAbilityContext,
new AnyJSBundleProvider([
new ResourceJSBundleProvider(
this.rnohCoreContext!.uiAbilityContext.resourceManager,
'bundle.harmony.js'
)
]),
'bundle.harmony.js'
);
RNApp({
rnInstanceConfig: {
createRNPackages
},
appKey: 'YourApp',
jsBundleProvider
});可选接管重启通知
import { CodePushRestartManager } from '@oh-rn/react-native-code-push';
CodePushRestartManager.addRestartListener((request) => {
console.info('CodePush restart requested:', request.reason);
return false;
});接口文档
快速验证(运行 Example)
前置条件
| 依赖版本要求 | | |-------------|---| | Node.js | >= 20(示例准备脚本要求) | | DevEco Studio | 6.1.1 | | HarmonyOS SDK | 示例工程 target API 23 |
运行步骤
1. 克隆仓库
git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/bravemobile-react-native-code-push.git
cd bravemobile-react-native-code-push2. 安装 npm 依赖并生成 JS Bundle
当前仓库的可运行入口是 example/harmony;example_auto/harmony 用于自动化验证。先在对应的 React Native 示例根目录执行:
cd example
npm install --legacy-peer-deps
npm run dev如需运行自动化验证工程:
cd example_auto
npm install --legacy-peer-deps
npm run dev3. 安装鸿蒙依赖并编译 HAP
cd harmony
ohpm install --all
hvigorw --mode module -p module=entry@default -p product=default -p buildMode=release assembleHap --no-daemon4. 用 DevEco Studio 打开鸿蒙工程(可选)
- 打开 DevEco Studio。
- 选择
example/harmony(或example_auto/harmony)目录。 - 等待 Sync 完成。
- 在 DevEco Studio 中确认自动签名配置已启用。
5. 运行 HAP
在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备或模拟器。
注意:Example 工程从 npmjs 安装
@hxa-rn/react-native-code-push,并复用包内 HAR;无需额外执行npm pack或手动配置 Link。Example 已声明ohos.permission.INTERNET,CodePush 运行时默认加载bundle.harmony.js;如需验证热更新,请按“宿主侧 Bundle Provider”章节配置发布历史和CodePushJSBundleProvider。
约束与限制
兼容性
| 项 | 版本 / 说明 |
|----|------|
| React Native | 0.72+,示例工程使用 0.72.5 |
| RNOH | 依赖 @react-native-oh/react-native-harmony 与 @rnoh/react-native-openharmony,版本以宿主工程 RNOH 配置为准 |
| Node.js | >=18;运行随库示例工程时建议使用 >=20 |
| 鸿蒙 SDK | 以宿主 RNOH 工程为准;随库示例工程为 compatibleSdkVersion 5.0.1(13),targetSdkVersion 6.1.0(23) |
| 工程模型 | React Native + RNOH 工程,鸿蒙侧通过 ArkTS HAR 和 TurboModule 接入 |
| 支持设备类型 | 鸿蒙模块声明 default、tablet、2in1 |
| 上游形态 | Android / iOS 原生模块与 JS 层 CodePush API |
| 鸿蒙侧形态 | RNOH TurboModule、ArkTS HAR、宿主 CodePushJSBundleProvider 接线 |
权限
本库依赖 ohos.permission.INTERNET,用于下载更新包、读取发布历史地址和上报部署状态。该权限为 normal 级别,无需运行时弹窗;宿主工程需要在入口模块声明网络权限。本库不申请位置、相机、麦克风、通讯录、电话、短信或账号类权限;更新包与状态数据保存在应用沙箱内。
功能约束
- 自托管发布历史:本库不内置发布服务,调用方必须实现
releaseHistoryFetcher并返回符合 CodePush 结构的发布历史数据。 - bundle 文件名:更新包内 bundle 文件名应与
CodePushJSBundleProvider第三个参数一致,默认使用bundle.harmony.js。 - 宿主接线要求:宿主必须把
CodePushJSBundleProvider接入 RNApp,否则重建 RN 实例后仍可能加载内置 bundle。 - 内置包摘要:
getConfiguration().packageHash依赖宿主构建流程提供CodePushHashrawfile;未提供时该字段可以为空,其他配置字段不受影响。 - 换包边界:运行期更新覆盖 RN JS Bundle、样式、文案和随更新包下发的资源;原生安装包声明、权限、Ability、HAR、so 与 ArkTS 原生代码需要通过应用版本更新完成。
- 大包耗时:更新包下载、解压、差分合并和 SHA-256 校验会占用一定时间,业务侧建议展示进度并避免在关键交互中触发大包更新。
- 调试服务影响:接入 Metro 调试服务时,Metro bundle 可能覆盖沙箱更新包;验证换包效果时建议使用内置 bundle 与沙箱更新包组合。
开源 License
本项目基于 MIT License 开源,与上游 Soomgo-Mobile/react-native-code-push 协议一致。请自由地享受和参与开源。
