⚠️ For Your Infomation:笔者非专业客户端开发人员,以下分析过程并不保证完全正确,并且加载过程是点到为止,不涉及 JS 解析与 OC 底层部分,请酌情阅读 以下代码基于 React Native 0.70.0 版本分析

RCTBridge

在阅读本文前,您有必要需要了解 RCTBridge。根据其头文件的注释,它是这么被定义的:

/**
 * Async batched bridge used to communicate with the JavaScript application.
 */
@interface RCTBridge : NSObject <RCTInvalidating>

也就是说 RCTBridge 是个用来与 JS 批量且异步通讯的桥,其作用类似于微信小程序用于 Webview 与 Native 通讯的 JSBridge。

在前一篇文章中,您已经了解到 JSBundle 具体位置,为了溯源 JSBundle 的加载,就需要了解谁调用了 sourceURLForBridge。通过搜索源码,可找到是在 RCTBridge 初始化的时候调用的。

// React/Base/RCTBridge.m

- (void)setUp
{
	// ...
  Class bridgeClass = self.bridgeClass;

  // Only update bundleURL from delegate if delegate bundleURL has changed
  NSURL *previousDelegateURL = _delegateBundleURL;
  _delegateBundleURL = [self.delegate **sourceURLForBridge:self**];
  if (_delegateBundleURL && ![_delegateBundleURL isEqual:previousDelegateURL]) {
    _bundleURL = _delegateBundleURL;
  }

  // 获取 bundle 绝对路径
  _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString];

												// bridgeClass = RCTCxxBridge
  self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self];
  [self.batchedBridge start];
}

在得到 Bundle 地址后,会初始化 RCTCxxBridge(bridgeClass),并赋值给 batchedBridge 属性,然后执行 batchedBridgestart 方法,也就是 RCTCxxBridge.start()

RCTCxxBridge.initWithParentBridge 不作过多解释,这里的核心工作是将挂载 RCTBridgeRCTCxxBridge 上,还有一些非必要的事件与日志注册

bridgeClass 可理解为是一种依赖倒置,这里传入的是 RCTCxxBridge 的实现(早期版本是 RCTBatchedBridge

RCTCxxBridge.start

start 函数主要工作如下:

  1. 注册 RCTJavaScriptWillStartLoadingNotification 事件,即 JS 线程启动前事件
  2. 创建 JS 线程
  3. 创建 JS 任务队列
  4. 初始化 RCTModuleRegistry 注册 Native Modules
  5. 实例化 react.Instance (使用 C++ 实现)对象,并挂载到 this
  6. 配置 JS 引擎(JSC / Hermes)
  7. 初始化 TurboModuleRegistry,即 TurboModule 的注册入口(这里先跳过)