「前端」带你走近ReactNative启动流程与通讯机制

344 阅读4分钟

ReactNative是什么

React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,支持iOS和安卓两大平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。号称:Learn once, write anywhere

源码官网:https://github.com/facebook/react-native


React Native主要特性:

  • 支持原生iOS组件
  • 异步执行
  • 触摸处理
  • 引入 Flexbox 布局模型和样式
  • 具有较强的可扩展性


谁在用ReactNative?从ReactNative的官网上,我们可以看到,以下公司正在使用或者曾经使用了ReactNative结构。

「前端」带你走近ReactNative启动流程与通讯机制

「前端」带你走近ReactNative启动流程与通讯机制


ReactNative是怎么被加载执行的?

首先,写一段很简单的ReactNative代码:

「前端」带你走近ReactNative启动流程与通讯机制


iOS客户端启动时,通过执行下面的代码,加载ReactNative的根视图。

「前端」带你走近ReactNative启动流程与通讯机制


程序运行起来后,你会看到下图的界面,是带原生的视图应用程序!

「前端」带你走近ReactNative启动流程与通讯机制


就这么简单的十来行代码,你就可以实现一个带原生视图的应用,太神奇了。那么你会要问,这么简单的几行代码,怎么就能驱动底层,生成原生应用呢?其实,ReactNative框架和工具集帮你做了很大一部分的事情。


「前端」带你走近ReactNative启动流程与通讯机制


通过打包编译脚本,编译后的JSBundle文件是很大的,就刚才的那段代码,编译后的JSBundle足足有645KB,里面的内容很复杂。

react-native bundle --platform ios --entry-file index.js --bundle-output ./bundle/ios/index.ios.bundle --dev false


「前端」带你走近ReactNative启动流程与通讯机制


「前端」带你走近ReactNative启动流程与通讯机制


在讲JSBundle加载之前,我们需要先了解ReactNative的核心驱动JavaScriptCore


什么是JavaScriptCore?

ReactNative的核心驱动力就来自于JSEngine.所有JS和JSX代码都会被JSEngine来执行。在iOS上,默认的JSEngine就是JavaScriptCore, iOS 7之后的设备都支持。JavaScriptCore来自于WebKit, 所以,安卓上默认也是用JavaScriptCore。JavaScriptCore是JavaScript的虚拟机,为JavaScript的执行提供底层资源。在浏览器中,所处的位置如下:

「前端」带你走近ReactNative启动流程与通讯机制


JavaScriptCore主要由以下模块组成:

  • Lexer 词法分析器,将脚本源码分解成一系列的Token
  • Parser 语法分析器,处理Token并生成相应的语法树
  • LLInt 低级解释器,执行Parser生成的二进制代码
  • Baseline JIT 基线JIT(just in time 实施编译)
  • DFG 低延迟优化的JIT
  • FTL 高通量优化的JIT


以IOS客户端启动为例,下面讲解ReactNative的启动加载流程


阶段一、 [创建RCTRootView] ->[创建RCTBridge] -> [调用[RCTCxxBridge start]

1.创建JS线程

2.初始化NativeModule

3.创建<JSIExecutorFactory> executorFactory

4.在js线程初始化通讯桥

6.运行js文件(将加载的JS文件交给JSCore解析执行)


阶段二、创建ContentView并加载应用

一是创建RCTRootContentView,并在view上加上一个手势识别器,然后在bridge.uiManager中注册自己。

二是加载应用

[bridge enqueueJSCall:@"AppRegistry"

method:@"runApplication"

args:@[moduleName, appParameters]

completion:NULL];

执行完后,执行回调方法callNativeModules,最终回调给native模块

关键的JaveScript类AppRegistry。

AppRegistry所有 React Native 应用的 JS 入口。应用的根组件应当通过AppRegistry.registerComponent方法注册自己,然后原生系统才可以加载应用的代码包并且在启动完成之后通过调用AppRegistry.runApplication来真正运行应用。


1.ReactNative代码,定义App,并注册

「前端」带你走近ReactNative启动流程与通讯机制


AppRegistry.registerComponent的代码实现

「前端」带你走近ReactNative启动流程与通讯机制


iOS客户端启动程序,运行对用的ReactNative应用

「前端」带你走近ReactNative启动流程与通讯机制

「前端」带你走近ReactNative启动流程与通讯机制


AppRegistry.runApplication的实现

「前端」带你走近ReactNative启动流程与通讯机制


总体而言,ReactNative的技术架构如下:

「前端」带你走近ReactNative启动流程与通讯机制


ReactNative的通讯机制

1.ReactNative页面调用原生的方法

Native中,写一个实现“RCTBridgeModule”协议的Objective-C类

「前端」带你走近ReactNative启动流程与通讯机制


通过RCT_EXPORT_METHOD宏,暴露方法

「前端」带你走近ReactNative启动流程与通讯机制

「前端」带你走近ReactNative启动流程与通讯机制


2.原生方法通知ReactNative页面

Native代码中,定义一个类,继承自 RCTEventEmitter

「前端」带你走近ReactNative启动流程与通讯机制

当原生代码需要通知ReactNative页面时,通过sendEventWithName:body:将事件与参数广播给ReactNative页面。


「前端」带你走近ReactNative启动流程与通讯机制


当然,ReactNative页面需要注册监听对用的事件,代码如下:

「前端」带你走近ReactNative启动流程与通讯机制


参考资料:

RN源码:https://github.com/facebook/react-native

RN官方文档( Getting-Started ):https://facebook.github.io/react-native/

中文:https://reactnative.cn/docs/getting-started/

React Native源代码分析--IOS客户端启动流程(从OC到JS)

https://www.jianshu.com/p/b58f22c079e6

React Native剖析

https://www.jianshu.com/p/353974a79712

JavaScriptCore全面解析

https://segmentfault.com/a/1190000017983911