‌React Native架构与源码深度解读‌

# React Native 架构与源码深度解读

React Native(以下简称 RN)凭借“一次编写,多端运行”的理念,迅速在移动开发领域崛起。本篇文章将从整体架构层面入手,逐步深入其底层源码,包括 JS 与原生桥接机制、渲染双引擎、Fabric 架构、TurboModules、架构演变和示例代码解析。文章结构如下:

1. [前言:为什么要深度解读 React Native](#前言为什么要深度解读-react-native)  
2. [整体架构概览](#整体架构概览)  
   1. [JavaScript 线程与原生线程分离](#javascript-线程与原生线程分离)  
   2. [桥接(Bridge)机制](#桥接bridge机制)  
   3. [UI 管道:从 JS 到原生视图](#ui-管道从-js-到原生视图)  
3. [旧架构:Bridge+ShadowTree 渲染流程](#旧架构bridgeshadowtree-渲染流程)  
   1. [JavaScriptCore 与 Metro Bundler](#javascriptcore-与-metro-bundler)  
   2. [Shadow Tree(阴影树)与布局计算](#shadow-tree阴影树与布局计算)  
   3. [Bridge 调用与异步队列](#bridge-调用与异步队列)  
   4. [示例:自定义 Native Module](#示例自定义-native-module)  
4. [新架构:Fabric & TurboModules](#新架构fabric--turbomodules)  
   1. [为何引入 Fabric?旧架构不足点](#为何引入-fabric旧架构不足点)  
   2. [Fabric 渲染管线核心](#fabric-渲染管线核心)  
   3. [TurboModules:更高效的原生模块访问](#turbomodules更高效的原生模块访问)  
   4. [示例:TurboModule 定义与调用](#示例turbomodule-定义与调用)  
5. [架构图解与流程示意](#架构图解与流程示意)  
6. [源码剖析重点文件与目录](#源码剖析重点文件与目录)  
   1. [`ReactAndroid/` 目录结构](#reactandroid-目录结构)  
   2. [`ReactCommon/` 目录要点](#reactcommon-目录要点)  
   3. [`React/RCTModule/` 与 `Fabric/`](#reactrctmodule-与-fabric)  
7. [架构演进与性能优化点](#架构演进与性能优化点)  
   1. [从 “Bridge-only” 到 “Turbo” 路线图](#从-bridge-only-到-turbo-路线图)  
   2. [JSC → Hermes 引擎切换](#jsc--hermes-引擎切换)  
   3. [Concurrent React 兼容与异步更新](#concurrent-react-兼容与异步更新)  
8. [React Native 常见性能调优实践](#react-native-常见性能调优实践)  
9. [总结与学习建议](#总结与学习建议)  

---

## 前言:为什么要深度解读 React Native

对 RN 源码进行深度研究,可以帮助我们:

1. **理解性能瓶颈来源**:了解 JS 和原生交互、渲染流程,有助于定位性能热点。  
2. **自定义 Native 组件**:知道桥接如何工作,才能正确编写高性能的自定义原生模块和视图组件。  
3. **紧跟架构演进**:Fabric、TurboModules、Hermes 和 Concurrent React 都在不断演进,深入源码才能快速上手并解决兼容问题。  
4. **提高开发效率**:借鉴 RN 架构设计思想,优化自己的项目结构和工程化方案。  

下面逐层剖析 RN 底层管理 JS、原生模块与 UI 渲染的关键技术细节,帮助你迅速理清全局脉络。

---

## 整体架构概览

React Native 将移动端应用分为两部分:**JavaScript 线程** 与 **原生线程**(UI 线程 + Java/Kotlin、Objective-C/Swift 层)。它们通过桥接(Bridge)进行异步通信。整体架构可分为三大模块:

1. **JS 引擎与逻辑执行**  
   - 内置 JavaScriptCore(iOS)或使用 Hermes(Android/iOS),执行用 React 语法编写的业务逻辑与 UI 声明。  
   - `Metro Bundler` 将所有 JS 模块打包成单一 `index.bundle`(或多个分块 bundle),供手机端加载。  

2. **桥接(Bridge)层**  
   - 负责在 JS 线程与原生线程之间进行消息编解码。旧架构使用 JSON 序列化,成为性能瓶颈;新架构下的 TurboModules 和 JSI(JavaScript Interface) 通过共享 C++ 对象指针,大大降低了往返开销。  

3. **UI 管道**  
   - **旧架构**:JS 计算出最终的 Shadow Node 树(阴影树),并通过 Bridge 把变更下发到原生 Shadow Tree 模块,由 Yoga 计算布局,生成具体坐标后再下发通过 UIManager 进行原生 View 的增删改操作。  
   - **新架构 Fabric**:直接在 C++ 层面管理“Shadow Tree”并使用 JSI 直接回调布局与渲染接口,整个流程更底层、更细粒度、更高效。  

下图简要展示两种架构的对比流程:  

旧架构(Bridge + Shadow Tree) 新架构(Fabric + TurboModules)
╔════════════════════════════╗ ╔════════════════════════════╗
║ JS 线程(JSC/Hermes) ║ ║ JS 线程(JSC/Hermes) ║
║ React 组件与业务逻辑 ║ ║ React 组件与业务逻辑 ║
╠════════════════════════════╣ ╠════════════════════════════╣
║ Shadow Props → JSX 元素 ║ ║ JSX 元素 → JSI 直接调用 C++ ║
║ (虚拟 DOM 树) ║ ║ Fabric Shadow Node 构建 ║
╠════════════════════════════╣ ╠════════════════════════════╣
║ Bridge(JSON 序列化) ║◀─────────▶ ║ JSI(Host Object / Host ║
║ 发送更新指令到 Native ║ ║ Function) ║
╠════════════════════════════╣ ╠════════════════════════════╣
║ Native 阴影树(Yoga 计算) ║ ║ C++ 阴影树(Yoga/新版布局) ║
║ 计算最终布局 → UIManager ║ ║ 直接在 C++ 执行布局与渲染 ║
╠════════════════════════════╣ ╠════════════════════════════╣
║ UI 线程:原生 View 操作 ║ ║ UI 线程:原生 View 操作 ║
╚════════════════════════════╝ ╚════════════════════════════╝


下面我们分章节详细说明各个模块的核心工作原理与源码实现思路。

---

## 旧架构:Bridge+ShadowTree 渲染流程

在 RN 0.60 以前,核心架构主要依赖桥接(Bridge)和 Yoga 布局(由 Facebook 开源)。这一套架构虽已逐渐被 Fabric 取代,但理解它对后续学习 Fabric 和 TurboModules 非常重要。

### JavaScriptCore 与 Metro Bundler

1. **JavaScriptCore(JSC)**  
   - RN 默认在 iOS 平台使用 iOS 系统自带的 JSC;在 Android 端原先也依赖社区提供的 JSC 库,后来可以选择使用 Hermes。  
   - JSC 会在 App 启动时将 `main.jsbundle` 加载到内存,启动一个 JS 线程。此线程执行 React 业务逻辑、Hooks、状态更新和渲染计算。  

2. **Metro Bundler**  
   - `Metro` 是 RN 的打包工具,会把各个 JS 模块打包成一个(或多个)可供原生端加载的 bundle。例如:`index.android.bundle`、`index.ios.bundle`。  
   - 支持 source maps,以便调试。  

3. **JS 线程入口**  
   - 在 iOS `AppDelegate.m` 的 `didFinishLaunching` 中,会调用:
     ```objc
     RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
     RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"YourAppName" initialProperties:nil];
     ```
   - `RCTBridge` 会加载本地或远程 `main.jsbundle`,创建一个 `JSContext`,并在其中执行 `AppRegistry.registerComponent('YourAppName', () => App);` 注册根组件。  

### Shadow Tree(阴影树)与布局计算

在旧架构中,RN 维护了两棵树:**Shadow Tree(ShadowNode)** 和真实 **View Tree(UIView/Android View)**。Shadow Tree 负责布局计算和离屏差分,最终再将变化下发真实 View 对象。

1. **ShadowNode**  
   - 对应 RN 中每个 JS 组件的“原生阴影节点”,定义在 `ReactCommon/yoga` 或 `React/CoreModules/RCTUIManager` 中。ShadowNode 只存储布局属性(如 `flex`、`margin`、`padding`、`width`、`height`)。  
   - ShadowNode 树的构建基于 JS 端调用 `React.createElement` 产生的虚拟 DOM,当 JS 调用 `setState` 或 `props` 发生变化时,新的 ShadowNode 会重新进入布局计算。  

2. **Yoga 布局引擎**  
   - Facebook 开源的跨平台布局库(基于 FlexBox 算法),通过对 ShadowNode 树执行 `YGNodeCalculateLayout`,得到每个节点最终的 `x, y, width, height`。  
   - ShadowNode 的属性会同步设置到 Yoga 中间层,为布局计算提供依据。  

3. **Bridge 下发 UI 操作**  
   - 当 ShadowNode 布局计算完成后,RN 会遍历 Shadow Tree,对比新旧布局差异,将每个需要移动、插入或删除的 ShadowNode 生成一条 “UI 编辑指令(UIOperation)” → 通过 Bridge 发送给原生端的 UIManager。  
   - UIManager 将这些指令转换为对应的 `UIView`(iOS)或 `ViewGroup`(Android)操作,例如 `createView`、`updateView`、`manageChildren`。  

4. **示例:ShadowNode 更新流程**  
   - JS 端调用 `setState` → 触发 `RCTExecuteOnJavaScriptQueue` 执行组件 render → 新旧虚拟 DOM 差分 → 调用 `UIManager.createView` / `UIManager.updateView` → ShadowNode 属性更新 → Yoga 重新计算 → 生成布局结果 → UIManager 下发真实 View 更新 → 原生 UI 线程执行相应操作。  

### Bridge 调用与异步队列

桥接层将 JS 与原生分离,通过异步消息队列通信。核心实现 resides 于:

- **iOS:`RCTBridge.mm` 与 `RCTBatchedBridge`**  
- **Android:`CatalystInstanceImpl.java` **  

1. **信息编码**  
   - 旧架构将需要传递的参数(如创建 View 时的属性字典)序列化为 JSON 数组,再通过 JNI(Android)或 Objective-C 原生函数(iOS)发送给对端。  
   - 此种方式的缺点在于 JSON 序列化开销大、内存分配频繁、跨线程上下文切换耗时。  

2. **异步队列**  
   - JS 线程将所有桥接请求(例如 `UIManager.createView(...)`、`NativeModules.YourModule.yourMethod(...)`)推入一个被称为 “Batched Bridge Queue” 的队列,定期打包成一批消息下发给原生。  
   - 原生执行完成后,可选择通过回调将结果再回传给 JS。  

3. **示例:调用 Native Module**  
   - JS 端代码:
     ```js
     import { NativeModules } from 'react-native';
     NativeModules.ToastModule.show('Hello from JS!', NativeModules.ToastModule.SHORT);
     ```
   - JS 线程将这条调用封装成 `["ToastModule", "show", ["Hello from JS!", 0]]`,放入 BatchedBridge 队列。  
   - 原生端收到 JSON 消息后,在相应 Module 中找到 `show` 方法并执行。  

### 示例:自定义 Native Module

下面演示如何在旧架构下为 Android 创建一个简单的 Toast Module。

1. **创建 Java 类 `ToastModule.java`**  
   ```java
   // android/app/src/main/java/com/yourapp/ToastModule.java
   package com.yourapp;

   import android.widget.Toast;
   import com.facebook.react.bridge.ReactApplicationContext;
   import com.facebook.react.bridge.ReactContextBaseJavaModule;
   import com.facebook.react.bridge.ReactMethod;

   public class ToastModule extends ReactContextBaseJavaModule {
     private static ReactApplicationContext reactContext;

     public ToastModule(ReactApplicationContext context) {
       super(context);
       reactContext = context;
     }

     @Override
     public String getName() {
       return "ToastModule";
     }

     @ReactMethod
     public void show(String message, int duration) {
       Toast.makeText(reactContext, message, duration).show();
     }
   }
  1. 创建 ToastPackage.java

    // android/app/src/main/java/com/yourapp/ToastPackage.java
    package com.yourapp;
    
    import com.facebook.react.ReactPackage;
    import com.facebook.react.bridge.NativeModule;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.uimanager.ViewManager;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class ToastPackage implements ReactPackage {
      @Override
      public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ToastModule(reactContext));
        return modules;
      }
    
      @Override
      public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
      }
    }
  2. 注册到 MainApplication.java

    // android/app/src/main/java/com/yourapp/MainApplication.java
    @Override
    protected List<ReactPackage> getPackages() {
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // 手动添加
      packages.add(new ToastPackage());
      return packages;
    }
  3. JS 端调用示例

    // App.js
    import React from 'react';
    import { Button, NativeModules, View } from 'react-native';
    
    export default function App() {
      const { ToastModule } = NativeModules;
      return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Button
            title="Show Toast"
            onPress={() => ToastModule.show('Hello from RN!', ToastModule.SHORT)}
          />
        </View>
      );
    }

这样,当你按下按钮时,JS 端通过 Bridge 将调用下发到原生,执行 Toast.makeText 显示 Android 系统 Toast。


新架构:Fabric & TurboModules

为了解决 Bridge 性能瓶颈与布局卡顿问题,React Native 社区推出了新的架构方案:Fabric 渲染管线TurboModules。自 RN 0.62 起分步引入,RN 0.65+ 已支持并逐渐默认启用。

为何引入 Fabric?旧架构不足点

  1. Bridge 性能瓶颈

    • JSON 序列化与反序列化开销大,往返耗时明显。
    • Shadow Tree → Layout → UI 操作需要多次跨桥,UI 更新延迟。
  2. 无法细粒度调度布局

    • 旧架构 ShadowNode 计算与 UI 更新合并在一起,难以“中断”或“并发处理”子树,更难适配 Concurrent React。
  3. 原生模块加载不够灵活

    • NativeModules 以“静态注册”为主,不支持按需加载,高数量原生模块时耗时且占内存。

Fabric 渲染管线核心

Fabric 架构在 C++ 层面实现了 Shadow Tree,核心思想是将布局与渲染管线下沉到 C++,并借助 JSI(JavaScript Interface)将它暴露给 JS,从而使 JS 与原生能在同一个事件循环中交互,无需通过异步 Bridge。

  1. JSI(JavaScript Interface)

    • JSI 是一套在 JS 引擎(JSC 或 Hermes)与 C++ 之间的通信接口。与旧 Bridge 不同,JSI 直接将 C++ 对象注入到 JS 全局变量中,避免 JSON 序列化/反序列化。
    • FabricUIManagerTurboModuleManager 等都通过 JSI 注册为 JS 可调用的对象(Host Object / Host Function)。
  2. Fabric Shadow Tree

    • ShadowNode 转移到 C++,并使用 Yoga(或重写的 C++ 布局引擎)计算布局。
    • JS 通过 JSI 直接调用 FabricUIManager.createNode(tag, props, rootTag) 创建 ShadowNode;
    • 当组件更新时,JS 端调用 FabricUIManager.updateNode(node, newProps),C++ 端更新布局属性并触发重排。
  3. 同步调用与并发

    • Fabric 支持 JS 与原生在同一线程进行布局与渲染交互,可灵活支持 Concurrent React。
    • 在 C++ 层使用“Reconcile on UI Thread”模式,让 UI 更新更流畅,减少卡顿。
  4. 示意流程

    JS 线程(Hermes/JSC)               C++ 层(Fabric)       原生 UI 线程
    ┌─────────────────────────────┐        ┌────────────────────┐
    │ React render() → JSX 树      │        │                    │
    │ createNode(hostType, props)  │ ──┐   │                    │
    └─────────────────────────────┘   │   │                    │
                                      │   │   Fabric Shadow Tree │
    ┌─────────────────────────────┐   │   │  layoutWithYoga()     │
    │ updateProps(node, newProps) │ ──┼──▶│  计算 x,y,width,height │
    └─────────────────────────────┘   │   └────────────────────┘
                                      │           │
                                      │           ▼
                                      │   ┌────────────────────┐
                                      │   │ UI Commands List   │
                                      │   │(e.g. createView/   │
                                      │   │ updateView/ remove)│
                                      │   └────────────────────┘
                                      │           │
                                      │           ▼
    JS 可并发调度(Concurrent Mode)    │   ┌────────────────────┐
    └─────────────────────────────┘        │    原生 UI 线程       │
                                           │  apply UI Commands   │
                                           └────────────────────┘

TurboModules:更高效的原生模块访问

TurboModules 架构将旧的 NativeModules 静态注册替换为按需加载的模块系统,主要特点如下:

  1. JSI 桥接

    • 通过 JSI 将每个原生模块(C++ / Java / Objective-C)注册为一个 Host Object,在 JS 端直接读取,这种方式无须异步 Bridge,调用更快。
  2. 按需加载

    • 模块仅在首次调用时加载,大大减少冷启动时的开销。
    • 不再需要在 MainApplication.java 中手动注册所有模块,而是遵循约定目录 ReactCommon/turbomodule/ 或 Gradle 配置自动生成。
  3. 异步与同步方法支持

    • TurboModules 支持直接返回同步值(如获取设备信息)或使用 Promise(异步)。
    • 通过 JSI 将回调和 Promise 直接挂到 JS 引擎上,无需 JSON 序列化。
  4. 示例:定义一个简单的 TurboModule
    以下以 iOS 为例,演示在 new architecture 下创建一个简单的 DeviceInfo TurboModule。

    1. Objective-C++ 接口声明

      // ios/ReactNativeNewArch/DeviceInfoModule.h
      #import <React/RCTBridgeModule.h>
      #import <ReactCommon/RCTTurboModule.h>
      #import <React/RCTMethodInfo.h>
      
      @interface DeviceInfoModule : NSObject <RCTTurboModule>
      @end
    2. 实现 .mm 文件

      // ios/ReactNativeNewArch/DeviceInfoModule.mm
      #import "DeviceInfoModule.h"
      #import <UIKit/UIKit.h>
      #import <jsi/jsi.h>
      #import <React/RCTJSIUtils.h>
      
      using namespace facebook::jsi;
      
      @implementation DeviceInfoModule
      
      RCT_EXPORT_MODULE(DeviceInfo);
      
      // 在 Fabric+TurboModules 中,推荐使用 JSINativeModules 方式
      - (std::shared_ptr<facebook::react::CallInvoker>)getCallInvoker {
        return RCTCxxBridge_getJSCallInvoker(_bridge.compilerFlags);
      }
      
      - (void)install:(facebook::jsi::Runtime &)runtime
      {
        auto deviceInfo = Object::create(runtime);
        auto getSystemVersion = Function::createFromHostFunction(
          runtime,
          PropNameID::forAscii(runtime, "getSystemVersion"),
          0,
          [](Runtime &rt, Value const &, Value const *args, size_t) -> Value {
            NSString *version = [UIDevice currentDevice].systemVersion;
            std::string ver = [version UTF8String];
            return String::createFromUtf8(rt, ver);
          }
        );
        deviceInfo.setProperty(runtime, "getSystemVersion", getSystemVersion);
        runtime.global().setProperty(runtime, "DeviceInfo", deviceInfo);
      }
      
      @end
    3. JS 端调用示例

      // 在 DevTools 中调试
      console.log(DeviceInfo.getSystemVersion()); // e.g. "14.4"

    这段代码利用 JSI 将 DeviceInfo.getSystemVersion() 直接挂载到 JS 全局,通过 C++/Objective-C++ 获取系统版本并返回,无需走 Bridge。


架构图解与流程示意

下面汇总一个较为完整的架构图,帮助你理清旧架构与新架构中各个模块的职责与调用链路。图中以箭头表示调用方向、数据流转路径。

┌─────────────────────────────────────────────────────────────────────────┐
│                             JS 线程(JSC / Hermes)                    │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                         React 应用层                              │   │
│   │   App.js → 组件树 → Hooks / Redux / 状态管理 → JSX 构建虚拟 DOM       │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│             │               │           │             │                 │
│             ▼               ▼           ▼             ▼                 │
│   ┌──────────────────┐  ┌────────┐  ┌────────────┐  ┌─────────┐           │
│   │ setState / dispatch │  │  navigate │  │ AsyncStorage │  │网络请求等│           │
│   └──────────────────┘  └────────┘  └────────────┘  └─────────┘           │
│             │                                                         │
│             ▼                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                       Fabric 管线 / 旧 Bridge                      │   │
│   │ ┌──────────────┐  ┌───────────────────┐  ┌─────────────────────┐ │   │
│   │ │ TurboModule   │  │  Bridge / JSI      │  │ UIManager / FabricUI │ │   │
│   │ │ (按需加载)    │  │ (JSON / HostObject)│  │   Shadow Nodes       │ │   │
│   │ └──────────────┘  └───────────────────┘  └─────────────────────┘ │   │
│   │       ▲                 ▲                      ▲               │   │
│   │       │                 │                      │               │   │
│   │       │  (方法调用)     │  (事件 / 更新)      │  (布局 / 渲染)  │   │
│   │       │                 │                      │               │   │
│   └───────┴─────────────────┴──────────────────────┴───────────────┘   │
│             │                 │                      │                 │
│             ▼                 ▼                      ▼                 │
│   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐       │
│   │  Native Modules  │  │ Shadow Tree /    │  │ Layout Engine    │       │
│   │  (Java / Obj-C)  │  │ Fabric C++ 节点   │  │  (Yoga or C++   )│       │
│   └──────────────────┘  └──────────────────┘  └──────────────────┘       │
│             │                 │                      │                 │
│             ▼                 ▼                      ▼                 │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        原生 UI 线程(iOS/Android)               │   │
│   │  ┌───────────────────────────────────────────────────────────┐ │   │
│   │  │             原生 View Hierarchy / Layer                  │ │   │
│   │  │  createView / updateView / manageChildren / removeView    │ │   │
│   │  └───────────────────────────────────────────────────────────┘ │   │
│   │         ▲                              ▲                        │   │
│   │         │                              │                        │   │
│   │         │  用户触摸事件 / 原生回调         │  Native Event 回传     │   │
│   │         │                              │                        │   │
│   └─────────┴──────────────────────────────┴────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘
  • JS 线程:负责业务逻辑、Hooks、组件树、状态更新、构建 ShadowNode / Fabric 指令,并通过 Bridge/JSI 与原生交互。
  • Fabric 管线 / 旧 Bridge:连接 JS 与原生。Fabric 下移 ShadowNode 到 C++,并借助 JSI 直接回调,Bridge 下旧有 JSON 串行化方式。
  • Native 线程:管理原生 View 层级,执行增删改操作,并将触摸等事件回传给 JS(例如 TouchableOpacityonPress)。

源码剖析重点文件与目录

RN 源码庞大,但对理解架构极为重要的目录集中在以下位置:

ReactAndroid/ 目录结构

  • ReactAndroid/src/main/java/com/facebook/react/

    • CatalystInstanceImpl.java:旧架构下 Bridge 核心实现,负责注册 Module、MessageQueue、调用 JS。
    • UIManagerModule.java:管理 ShadowNode、布局计算、最终下发 View 操作给原生。
    • ReactRootView.java:RN 根视图容器,加载 JS Bundle 并初始化 Bridge。
    • Fabric 子目录:Fabric 架构相关 Android 实现,包括 FabricUIManager.javaMountingManager.java
    • TurboModule 子目录:TurboModules 相关工厂和管理器,例如 TurboModuleManager.java
  • ReactAndroid/src/main/jni/

    • 包含 C++ 层面对 JSI、Fabric、Yoga 引擎的绑定。

ReactCommon/ 目录要点

  • jsi/

    • JSI 数据类型与接口定义,例如 jsi.hValue.hRuntime.h
  • jsiexecutor/

    • JSI 在 Android 与 iOS 上的桥接实现,例如 JSCRuntimeHermesRuntime
  • fabric/

    • Fabric C++ 核心代码,包含 ShadowNode 定义、事件调度、UIManager 接口。
  • turbomodule/

    • 定义了 TurboModule ABI,C++ / Java / Obj-C++ 通过这个接口生成对应的模块绑定。
  • yoga/

    • Facebook 开源的 Yoga 布局引擎源代码。

React/RCTModule/Fabric/

  • React/RCTModule/

    • 旧版 NativeModule 注册与调用机制,包含 RCTBridgeModule.hRCTBridge.h
  • Fabric/

    • iOS 端的 Fabric 相关目录,包含 RCTFabricUITurboModuleManager.mmRCTSurfacePresenter 等。

以上目录和文件是 RN 架构的核心,深入阅读这些源码可直接理解 RN 如何从 JS 调用原生、如何执行布局、如何同步渲染。


架构演进与性能优化点

从 “Bridge-only” 到 “Turbo” 路线图

  1. Bridge-only 架构(RN 0.59 及以前)

    • JSON 串行化 → native 执行 → JSON 反序列化,异步队列。
    • ShadowTree → Yoga 布局 → UIManager。
  2. TurboModules + Fabric(RN 0.62 – 0.66)

    • 使用 JSI 替代 JSON Bridge,NativeModules 改为 TurboModules,布局在 C++ 层面。
    • JS 与 UIManager 直接在同一线程交互,可实现“同步渲染”与“部分异步渲染”。
  3. Hermes 嵌入(RN 0.64 及以后)

    • Android 默认可切换到 Hermes,性能更优,内存占用更低。
    • JSC 下仍保留,但社区推荐使用 Hermes 以配合 Fabric / TurboModules。
  4. Concurrent React 兼容(RN 0.68+)

    • 支持 React 18 中的并发特性,Fiber reconciler 与 Scheduler 调度更紧密结合。
    • Fabric 管线结合 startTransitionuseDeferredValue 等并发 API,提升复杂 UI 的渲染流畅度。

JSC → Hermes 引擎切换

  • JSC(JavaScriptCore)

    • iOS 平台默认 JSC;Android 端曾经使用 jsc-android 二进制包。
    • 缺点:启动慢、内存占用高、缺乏及时更新。
  • Hermes

    • Facebook 自研的 JavaScript 引擎,针对 RN 做了裁剪,启动速度快、内存占用低。
    • RN 0.64+ 引入 hermes-engine,可通过 enableHermes: trueandroid/app/build.gradle 中启用:

      project.ext.react = [
        enableHermes: true,  // must be true to use Hermes
      ]
    • 相较 JSC,Hermes 在首包启动时间可提升约 25%\~40%,并在动画、JS 密集计算场景更流畅。

Concurrent React 兼容与异步更新

  • React 18 提出了“并发模式”,RN 也逐步支持:

    • 在 JS 端编写组件时,可使用 startTransition(() => setState(...)) 标记“可延迟更新”,允许 UI 在用户滚动、点击等操作中保持流畅。
    • Fabric 通过底层的 Scheduler 配合 JSI 调度,能在 UI 线程与 JS 线程之间分割任务,避免长时间占用导致卡顿。

React Native 常见性能调优实践

  1. 避免过度使用 Bridge

    • 批量调用 Bridge 操作(例如 UIManager),而非频繁单条调用。
    • 旧架构下可使用 UIManager.dispatchViewManagerCommand 一次传多个命令。
  2. 使用 FlatList 优化长列表

    • FlatList 支持 windowSizeinitialNumToRendermaxToRenderPerBatch 等属性,通过分片渲染列表项减轻 JS+UI 线程压力。
    • 利用 getItemLayout 提前告知每行高度,避免测量造成的抖动。
  3. 减少重绘与动画优化

    • 在大范围可动画控件上尽量启用 useNativeDriver: true,将动画交给原生驱动,避免 JS 持续插针。
    • 尽量减少在 render 中进行复杂计算,可用 useMemouseCallback 缓存。
  4. 避免匿名函数 & 重复创建对象

    • 在 JSX 中避免为每次 render 创建匿名函数或对象(如 style={{...}}),否则每次都会导致子组件重新渲染。
    • 将常用回调或样式提升到外部或使用 useCallback / useMemo 优化。
  5. 使用 Hermes 性能剖析工具

    • Hermes 自带的堆栈采样工具可分析 JS 侧的性能热点。
    • 借助 systrace 工具可更精准地剖析 UI 线程与 JS 线程之间的时间分配。
  6. 慎用 InteractionManager

    • 当任务量较重时,用 InteractionManager.runAfterInteractions 推迟到交互后执行,但若任务过多仍可能造成卡顿,应酌情使用。

总结与学习建议

本文从 RN 整体架构入手,深入解读了旧架构 Bridge + Shadow Tree 以及全新的 Fabric + TurboModules 管线,结合代码示例与架构图解,帮助你快速理清 RN 底层逻辑与演进路径。要真正掌握 RN 源码,建议采取如下学习路径:

  1. 阅读官方文档与架构设计文档

    • 官方博客经常发布架构演进文章。
    • React Native 核心仓库中的 Architecture.mdTurboModules.md 等文档非常有帮助。
  2. 从简单示例入手

    • 先实现一个自定义 Native Module,再升级为 TurboModule。
    • 逐步尝试手动创建 Fabric 节点并渲染。
  3. 调试与打断点

    • 在模拟器 / 手机上运行 RN 应用时,在 Xcode 或 Android Studio 对 CatalystBridgeFabricUIManager 等处打断点,观察 JS 与 Native 之间数据流转。
  4. 关注社区与 RFC

    • React Native 社区和 React Core 团队会定期在 GitHub 上发布 RFC(Request for Comments),讨论即将到来的架构变动。
    • 关注 react-native-website 中的 “Architecture” 栏目,及时了解新特性。
  5. 实践与迁移

    • 如果你有现有项目,尝试启用 Fabric 与 TurboModules,观察代码中需要修改的地方。
    • 在不同机型与平台上测试性能差异,积累实际经验。

通过持续的源码阅读与实践,相信你很快能深入理解 React Native 的底层原理,并能够在项目中定制高性能的原生组件或优化方案。

最后修改于:2025年05月29日 11:17

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日