React Native启动流程
现在,每当启动React Native应用程序时,要加载的第一个项目是本机入口点。Native线程产生JS VM线程,该线程运行捆绑的JS代码。JS代码具有应用程序的所有业务逻辑。JS基础设施初始化.主要是require等基本模块的加载并替换JS默认的实现。自定义require, Warning window, Alert window, fetch等都是在这里进行的。基础设施初始化好以后就可以开始加载js代码了。
Native线程现在通过RN Bridge发送消息以启动JS应用程序。现在,生成的Javascript线程开始通过RN Bridge向本机线程发出指令。说明包括要加载的视图,要从硬件检索的信息等。例如,如果JS线程想要创建视图和文本,它将把请求批处理为单个消息并将其发送到 用于渲染它们的本机线程。
[ [2,3,[2,'Text',{...}]] [2,3,[3,'View',{...
本机线程将执行这些操作并将结果发送回JS,以确保已执行操作。
原生代码初始化
这里讨论的主要是RN相关的原生代码和用户自定义的RN模块的原生代码的加载和初始化。原生代码初始化主要分两步:
-
静态加载。iOS没有动态加载原生代码的接口,所有的代码都在编译的初期就已经编译为静态代码并且链接好,程序启动的时候所有的原生代码都会加载好。这是原生代码的静态加载,iOS里面没有动态加载原生代码的概念,这也是为何没有静态代码热更新的原因。
-
RN模块解析和注入JS。这是加载的第二步。在RootView初始化的时候会遍历所有被标记为RCTModule的原生模块,生成一个json格式的模块信息,里面包含模块名称和方法名称,然后注入到JS Engine,由MessageQueue记录下来。原生代码在生成json模块信息的时候同时会在原生代码这边维护一个名称字典,用来把模块和方法的名称映射到原生代码的地址上去,用于JS调用原生代码的翻译。
Javascript环境初始化
RN的初始化是从RCRootView开始的,所有的绘制都会在这个RootView里面进行(Alert除外).RootView做的第一件事情就是初始化一个空的JS Engine。这个空的JS Engine里面包含一些最基础的模块和方法(fetch, require, alert等),没有UI绘制模块。RN的工作就是替换这些基础的模块和方法,然后把RN的UI绘制模块加载并注入到JS Engine。JS Engine不直接管理UI的绘制。
- 所有的绘制由原生控制的UI事件和Timer触发
- 影响界面刷新的事件发生以后一部分直接由原生控件消化掉,直接更新原生控件。剩下的部分会通过Bridge派发给MessageQueue,然后在JS层进行业务逻辑的计算,再由React来进行Virtual Dom的管理和更新。Virtual Dom再通过MessageQueue发送重绘指令给对应的原生组件进行UI更新。
Native Modules加载
在OC里面,所有NativeModules要加载进JS Engine都必须遵循一定的协议(protocol)。
模块(OC里面的类)需要声明为,然后在类里面还必须调用宏RCT_EXPORT_MODULE()用来定义一个接口告诉JS当前模块叫什么名字。这个宏可以接受一个可选的参数,指定模块名,不指定的情况下就取类名。
对应的JS模块在初始化的时候会调用原生类的[xxx new]方法.
模块声明为后只是告诉Native Modules这有一个原生模块,是一个空的模块。要导出任何方法给JS使用都必须手动用宏RCT_EXPORT_METHOD来导出方法给JS用.
所有的原生模块都会注册到NativeModules这一个JS模块下面去,你如果想要让自己的模块成为一个顶级模块就必须再写一个JS文件封装一遍NativeModules里面的方法。
你如果想自己的方法导出就默认成为顶级方法,那么你需要一个手动去调用JSC的接口,这个在前面章节有讲解。不建议这样做,因为这样你会失去跨JS引擎的便利性。
你可以导出常量到JS里面去,模块初始化的时候会坚持用户是否有实现constantsToExport方法,接受一个常量词典。
- (NSDictionary *)constantsToExport
{
return @{ @"firstDayOfTheWeek": @"Monday" };
}
常量只会在初始化的时候调用一次,动态修改该方法的返回值无效
所有标记为RCT_EXPORT_MODULE的模块都会在程序启动的时候自动注册好这些模块,主要是记录模块名和方法名。只是注册,不一定会初始化。
懒加载的模块
React Native的NativeModules是有延迟加载机制的。App初始化的时候
React Native JS接口兼容(Polyfills)
fetch替换
CommonJS Require
alert替换
console.warning替换
console.error替换