基于React Native 0.83.1 新架构下的拆包方案

React Native 0.83.1 新架构(New Architecture) 下的拆包方案


React Native 0.83.1 新架构拆包实战:基于 ReactHost 与单 Runtime 的动态加载方案

随着 React Native 进入 0.80+ 时代,新架构(Fabric & TurboModules)已成为主流。传统的基于 ReactInstanceManager 和 Bridge 的拆包方式已逐步过时。本文将介绍在 RN 0.83.1 版本下,如何利用 ReactHostJSIHermes 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 复制代码
<Stack.Navigator initialRouteName={props.biz || 'NotFound'}>
  <Stack.Screen name="NotFound" component={NotFound} />
  
  {/* 业务占位:有多少个拆分包,就配置多少个 Screen */}
  <Stack.Screen 
    key={'buz1'} 
    name={'buz1'} 
    component={BizShell} 
    options={{ headerShown: false }} 
  />
  <Stack.Screen 
    key={'buz2'} 
    name={'buz2'} 
    component={BizShell} 
    options={{ headerShown: false }} 
  />
</Stack.Navigator>

提示: 核心路由跳转与 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 中管理 reactNativeFactoryreactNativeDelegate,通过 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. 架构对齐: 深度集成 ReactHostRuntimeExecutor,完美兼容 Fabric 渲染引擎,是目前新架构下的最优实践。

发布建议:

  • 标签: React Native, Android, iOS, 拆包, 新架构, Hermes.
  • 摘要: 针对 React Native 0.83.1 最新版本,详细讲解如何在 Fabric 架构下实现单 Runtime 的业务拆包与动态加载。

项目git地址:gitee.com/liu_520/mul...

相关推荐
2501_916007471 天前
React Native 混淆在真项目中的方式,当 JS 和原生同时暴露
javascript·react native·react.js·ios·小程序·uni-app·iphone
qq_463408421 天前
React Native跨平台技术在开源鸿蒙中使用WebView来加载鸿蒙应用的网页版或通过一个WebView桥接本地代码与鸿蒙应用
javascript·算法·react native·react.js·开源·list·harmonyos
qq_463408422 天前
React Native跨平台技术在开源鸿蒙中查找最长回文子串的算法,使用中心扩展法(Center Expansion Algorithm)来实现这个功能
算法·react native·react.js·开源·harmonyos
qq_463408422 天前
React Native跨平台技术在开源鸿蒙中使用内置的`fetch` API或者第三方库如`axHarmony`来处理网络通信HTTP请求
javascript·算法·react native·react.js·http·开源·harmonyos
五点六六六2 天前
跨端RN 与 浏览器Web 的 长渲染性能 差异 与 底层 揭秘
前端·react native·webgl
sure2823 天前
在react native中实现短视频平台滑动视频播放组件
前端·react native
qq_463408423 天前
React Native跨平台技术在开源鸿蒙中开发一个奖励兑换模块,增加身份验证和授权机制(如JWT),以防止未授权的积分兑换
react native·开源·harmonyos
qq_463408424 天前
React Native跨平台技术在开源鸿蒙中开发一个具有全文搜索功能的组件,使用useMemo或useCallback来优化性能
react native·react.js·开源