# MultiBundlePrograms **Repository Path**: liu_520/multi-bundle-programs ## Basic Information - **Project Name**: MultiBundlePrograms - **Description**: rn拆包,基于React Native 0.83.1 新架构(New Architecture) 下的拆包方案 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 4 - **Created**: 2025-12-26 - **Last Updated**: 2026-01-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README React Native 0.83.1 新架构(New Architecture) 下的拆包方案 ![输入图片说明](SVID_20251226_160340_1.gif) --- # React Native 0.83.1 新架构拆包实战:基于 ReactHost 与单 Runtime 的动态加载方案 随着 React Native 进入 0.80+ 时代,新架构(Fabric & TurboModules)已成为主流。传统的基于 `ReactInstanceManager` 和 Bridge 的拆包方式已逐步过时。本文将介绍在 **RN 0.83.1** 版本下,如何利用 `ReactHost`、`JSI` 和 `Hermes Runtime` 实现高性能的模块化拆包与动态加载。 --- ## 一、 为什么旧的拆包方案失效了? 在新架构中,底层通信机制从传统的 JSON Bridge 转向了基于 C++ 的 **JSI (JavaScript Interface)**。 | 特性 | Legacy 架构 (旧) | 新架构 (Fabric + TurboModules) | | :--- | :--- | :--- | | **JS 执行环境** | Bridge + CatalystInstance | **JSI + Hermes Runtime** | | **Bundle 入口** | ReactInstanceManager | **ReactHost / JSExecutorFactory** | | **Native 管理器** | ReactActivity / ReactRootView | **ReactHost / ReactInstance** | | **JS 模块 API** | 全局注入模块 (Global Bridge) | **TurboModule + Codegen** | | **支持情况** | 已过时 (Deprecated) | **官方推荐** | > [!WARNING] > 从 RN 0.72 起 Fabric 默认启用,RN 0.80 之后已完全移除传统 Bridge 的 Fallback 机制。`JSBundleLoader` 等旧类在高性能新架构下已无法直接使用。 --- ## 二、 方案选择:多 Runtime vs 单 Runtime 在 0.83.1 版本下,实现多模块化主要有两种思路: 1. **多 ReactHost 实例化(隔离方案):** 每个业务模块独立打包,包含独立的基础库。优点是隔离性强,缺点是内存占用极高,无法共享基础库。 2. **单 Hermes Runtime 动态加载(推荐方案):** * **基础包 (Base Bundle):** 包含 RN 框架、NativeModules、公共库及导航容器。 * **业务包 (Business Bundle):** 仅包含业务代码,共用基础包的运行时。 * **优势:** 内存占用低、共用上下文、符合 Fabric 渲染链路。 **本文采用方案 2 进行深度实践。** --- ## 三、 核心原理 1. **按需加载:** 启动阶段只加载 `index.base.bundle`。 2. **动态注册:** 业务 Bundle 被加载时,通过 JSI 调用底层 C++ Runtime 的 `evaluateJavaScript` 执行 JS 代码,将业务页面注册到基础包的导航器(如 React Navigation)中。 3. **路由占位:** 基础包预留“壳页面”(BizShell),当导航跳转至业务模块时,若 Bundle 未加载则触发 Native 动态加载流程。 --- ## 四、 具体实现步骤 ### 1. React Native 层实现 #### 1.1 入口文件拆分 * **index.base.js (基础包):** ```javascript import { AppRegistry } from 'react-native'; import App from './src/App'; import { name as appName } from './app.json'; AppRegistry.registerComponent(appName, () => App); ``` * **index.buz1.js (业务包):** ```javascript import { registerBiz } from './src/navigation/DynamicRegistry'; import Buz1Navigator from './src/biz1/Navigator'; // 动态注册业务路由 registerBiz('buz1', Buz1Navigator); ``` #### 1.2 路由占位逻辑 在 `src/navigation/DynamicNavigator.tsx` 中,使用 `BizShell` 作为业务占位符: ```tsx {/* 业务占位:有多少个拆分包,就配置多少个 Screen */} ``` > **提示:** 核心路由跳转与 Bundle 加载状态维护均在 `BizShell.tsx` 中处理。 --- ### 2. Android 端核心代码 #### 2.1 初始化 ReactHost 在 `MainApplication` 中手动启动 `ReactHost` 并监听初始化状态。 ```kotlin private fun initializeReactHost() { val host = reactHost host.start() // 启动新架构 Host host.addReactInstanceEventListener(object : ReactInstanceEventListener { override fun onReactContextInitialized(reactContext: ReactContext) { // 将 Context 传给动态加载器 DynamicLoader.setContext(reactContext) try { // 执行 JSI 绑定或其他初始化 DynamicLoader.install() SplashActivity.instance?.hideLoading() } catch (e: Exception) { Log.e("MainApplication", "DynamicLoader 失败:${e.message}") } host.removeReactInstanceEventListener(this) } }) } ``` #### 2.2 动态加载 Bundle (NativeDynamicLoader.kt) 通过 JNI 获取 C++ Runtime 句柄并执行 JavaScript。 ```kotlin fun loadBundle(bundlePath: String) { val jsiPtr = context.javaScriptContextHolder.get() // 通过 JNI 调用 C++ 层的 evaluateJavaScript // 逻辑:判断 bundlePath 是否已加载 -> 未加载则读取文件并执行 nativeEvaluateJavaScript(jsiPtr, bundlePath) } ``` --- ### 3. iOS 端核心代码 #### 3.1 抽象 RNRuntimeManager 在 Swift 中管理 `reactNativeFactory` 和 `reactNativeDelegate`,通过 `rootViewFactory` 创建视图。 #### 3.2 动态加载 (RTNDynamicLoader) 在新架构下,不再使用过时的 `bridge.executeSourceCode`。 ```swift // JSBundleLoader.swift 核心逻辑 if let runtimeExecutor = rootViewFactory.reactHost.surfacePresenter?.runtimeExecutor { // 拿到 RuntimeExecutor 后,在 JS 线程执行业务代码 runtimeExecutor.execute { runtime in // 使用 C++ JSI 或内部 API 执行业务 Bundle 代码 loadBusinessBundle(path: bundlePath, in: runtime) } } ``` --- ## 五、 总结与优势 基于 RN 0.83.1 的这套拆包方案,完全摆脱了对 Legacy Bridge 的依赖: 1. **极速加载:** 利用 Hermes 字节码预编译,业务包加载近乎无感。 2. **灵活分发:** 业务 Bundle 可独立更新,无需重新安装 App。 3. **架构对齐:** 深度集成 `ReactHost` 和 `RuntimeExecutor`,完美兼容 Fabric 渲染引擎,是目前新架构下的最优实践。 --- **发布建议:** * **标签:** React Native, Android, iOS, 拆包, 新架构, Hermes. * **摘要:** 针对 React Native 0.83.1 最新版本,详细讲解如何在 Fabric 架构下实现单 Runtime 的业务拆包与动态加载。