React Native 0.83.1 新架構(gòu)(New Architecture) 下的拆包方案
React Native 0.83.1 新架構(gòu)拆包實戰(zhàn):基于 ReactHost 與單 Runtime 的動態(tài)加載方案
隨著 React Native 進入 0.80+ 時代,新架構(gòu)(Fabric & TurboModules)已成為主流。傳統(tǒng)的基于 ReactInstanceManager 和 Bridge 的拆包方式已逐步過時。本文將介紹在 RN 0.83.1 版本下,如何利用 ReactHost、JSI 和 Hermes Runtime 實現(xiàn)高性能的模塊化拆包與動態(tài)加載。
一、 為什么舊的拆包方案失效了?
在新架構(gòu)中,底層通信機制從傳統(tǒng)的 JSON Bridge 轉(zhuǎn)向了基于 C++ 的 JSI (JavaScript Interface)。
| 特性 | Legacy 架構(gòu) (舊) | 新架構(gòu) (Fabric + TurboModules) |
|---|---|---|
| JS 執(zhí)行環(huán)境 | 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 之后已完全移除傳統(tǒng) Bridge 的 Fallback 機制。JSBundleLoader等舊類在高性能新架構(gòu)下已無法直接使用。
二、 方案選擇:多 Runtime vs 單 Runtime
在 0.83.1 版本下,實現(xiàn)多模塊化主要有兩種思路:
- 多 ReactHost 實例化(隔離方案): 每個業(yè)務模塊獨立打包,包含獨立的基礎(chǔ)庫。優(yōu)點是隔離性強,缺點是內(nèi)存占用極高,無法共享基礎(chǔ)庫。
-
單 Hermes Runtime 動態(tài)加載(推薦方案):
- 基礎(chǔ)包 (Base Bundle): 包含 RN 框架、NativeModules、公共庫及導航容器。
- 業(yè)務包 (Business Bundle): 僅包含業(yè)務代碼,共用基礎(chǔ)包的運行時。
- 優(yōu)勢: 內(nèi)存占用低、共用上下文、符合 Fabric 渲染鏈路。
本文采用方案 2 進行深度實踐。
三、 核心原理
-
按需加載: 啟動階段只加載
index.base.bundle。 -
動態(tài)注冊: 業(yè)務 Bundle 被加載時,通過 JSI 調(diào)用底層 C++ Runtime 的
evaluateJavaScript執(zhí)行 JS 代碼,將業(yè)務頁面注冊到基礎(chǔ)包的導航器(如 React Navigation)中。 - 路由占位: 基礎(chǔ)包預留“殼頁面”(BizShell),當導航跳轉(zhuǎn)至業(yè)務模塊時,若 Bundle 未加載則觸發(fā) Native 動態(tài)加載流程。
四、 具體實現(xiàn)步驟
1. React Native 層實現(xiàn)
1.1 入口文件拆分
-
index.base.js (基礎(chǔ)包):
import { AppRegistry } from 'react-native'; import App from './src/App'; import { name as appName } from './app.json'; AppRegistry.registerComponent(appName, () => App); -
index.buz1.js (業(yè)務包):
import { registerBiz } from './src/navigation/DynamicRegistry'; import Buz1Navigator from './src/biz1/Navigator'; // 動態(tài)注冊業(yè)務路由 registerBiz('buz1', Buz1Navigator);
1.2 路由占位邏輯
在 src/navigation/DynamicNavigator.tsx 中,使用 BizShell 作為業(yè)務占位符:
<Stack.Navigator initialRouteName={props.biz || 'NotFound'}>
<Stack.Screen name="NotFound" component={NotFound} />
{/* 業(yè)務占位:有多少個拆分包,就配置多少個 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>
提示: 核心路由跳轉(zhuǎn)與 Bundle 加載狀態(tài)維護均在
BizShell.tsx中處理。
2. Android 端核心代碼
2.1 初始化 ReactHost
在 MainApplication 中手動啟動 ReactHost 并監(jiān)聽初始化狀態(tài)。
private fun initializeReactHost() {
val host = reactHost
host.start() // 啟動新架構(gòu) Host
host.addReactInstanceEventListener(object : ReactInstanceEventListener {
override fun onReactContextInitialized(reactContext: ReactContext) {
// 將 Context 傳給動態(tài)加載器
DynamicLoader.setContext(reactContext)
try {
// 執(zhí)行 JSI 綁定或其他初始化
DynamicLoader.install()
SplashActivity.instance?.hideLoading()
} catch (e: Exception) {
Log.e("MainApplication", "DynamicLoader 失?。?{e.message}")
}
host.removeReactInstanceEventListener(this)
}
})
}
2.2 動態(tài)加載 Bundle (NativeDynamicLoader.kt)
通過 JNI 獲取 C++ Runtime 句柄并執(zhí)行 JavaScript。
fun loadBundle(bundlePath: String) {
val jsiPtr = context.javaScriptContextHolder.get()
// 通過 JNI 調(diào)用 C++ 層的 evaluateJavaScript
// 邏輯:判斷 bundlePath 是否已加載 -> 未加載則讀取文件并執(zhí)行
nativeEvaluateJavaScript(jsiPtr, bundlePath)
}
3. iOS 端核心代碼
3.1 抽象 RNRuntimeManager
在 Swift 中管理 reactNativeFactory 和 reactNativeDelegate,通過 rootViewFactory 創(chuàng)建視圖。
3.2 動態(tài)加載 (RTNDynamicLoader)
在新架構(gòu)下,不再使用過時的 bridge.executeSourceCode。
// JSBundleLoader.swift 核心邏輯
if let runtimeExecutor = rootViewFactory.reactHost.surfacePresenter?.runtimeExecutor {
// 拿到 RuntimeExecutor 后,在 JS 線程執(zhí)行業(yè)務代碼
runtimeExecutor.execute { runtime in
// 使用 C++ JSI 或內(nèi)部 API 執(zhí)行業(yè)務 Bundle 代碼
loadBusinessBundle(path: bundlePath, in: runtime)
}
}
五、 總結(jié)與優(yōu)勢
基于 RN 0.83.1 的這套拆包方案,完全擺脫了對 Legacy Bridge 的依賴:
- 極速加載: 利用 Hermes 字節(jié)碼預編譯,業(yè)務包加載近乎無感。
- 靈活分發(fā): 業(yè)務 Bundle 可獨立更新,無需重新安裝 App。
-
架構(gòu)對齊: 深度集成
ReactHost和RuntimeExecutor,完美兼容 Fabric 渲染引擎,是目前新架構(gòu)下的最優(yōu)實踐。
發(fā)布建議:
- 標簽: React Native, Android, iOS, 拆包, 新架構(gòu), Hermes.
- 摘要: 針對 React Native 0.83.1 最新版本,詳細講解如何在 Fabric 架構(gòu)下實現(xiàn)單 Runtime 的業(yè)務拆包與動態(tài)加載。
項目git地址:https://gitee.com/liu_520/multi-bundle-programs
