在 RN 社区的 Upgrade Helper 中能够看到,从 0.67 版别到 0.68 版别的更新中有非常显眼的字眼:
React Native 0.68 includes preview of the New Architecture opt-in.
那么今天咱们就来看下 RN New Architecture 到底新在哪里。
新旧架构比照
开宗明义,咱们先来比照下新旧两个架构图。
旧架构图:
新架构图:
咱们能够显着看到新架构比较旧架构有着以下几点显着不同:
- 最左边 JS 层除了 React 之外,还引入了一个静态类型定义 Static Typs
- JS 打包成 JS Bundle 这步操作也不再强依赖 JS Core,任何 JS 引擎都能够完结
- JS 打包成 JS Bundle 后,不再是简单的经过 JSBridge 与 Native 层进行交互,而是要经过 JSI、Fabric、Turbo Modules 这三个新模块来完结与 Native 层的交互
- 在 JS 层和 JSI 之间,还有一个新东西叫 CodeGen
- JS 线程 与 用于布局的 Shadow 线程 之间的交互也不再需求经过 Native/UI 线程,直接经过 JSI 就能够完结交互
其中最要害的几个改变如下:
- JSI(Javascript Interface)
- Fabric
- Turbo Modules
- CodeGen
下面咱们来顺次看下这几个要害改变都带来了哪些重要的改变。
新旧通讯办法比照
旧架构的通讯办法
在旧架构中,JS 与 Native 之间的通讯是经过 JSBridge 来完结的。
当 JS 调用某个 Native 办法(比方敞开蓝牙权限)时,一般会履行以下事项:
- JS 线程将事件音讯序列化成 JSON
- JS 线程将序列化后的 JSON 信息传递给 JSBridge
- JSBridge 将信息传递给 Native 之前,会先将其反序列化
- Native 线程接收到反序列化后的信息,并履行对应的 Native 代码
旧的通讯办法存在以下问题:
- 一切音讯行列都是异步处理的。虽然大部分情景下异步处理是合理的,可是总避免不了需求同步调用的时分
- 音讯传递都需求经过序列化与反序列化,会带来额定的性能开销
- 对 Native 的调用是需求进行排队,批处理的
大部分时分Bridge的工作办法没问题,但有时分或许会发生堵塞现象。
比方当页面中有有个翻滚列表,需求翻滚时动态恳求数据并加载,这时分假如用户快速翻滚,或许就会出现白屏。
这是因为 Native 的翻滚事件会经过 JSBridge 传递给 JS 线程,JS 线程再去发送恳求获取下一步烘托数据,然后再将新的烘托数据经过 JSBridge 传递给 Native 线程。这些通讯进程都是异步的,就有或许导致页面空白。
新架构的通讯办法
前面说到的 JSI 支撑起了 RN 新架构的通讯办法。它是一个轻量级的通用层
,它是用 C++
完结的,能够让 JS 引擎直接调用到 Native 端的办法。
为什么说它是通用层呢?
旧架构运用的是 JSCore 引擎,而 JSBridge 只能兼容这个特定的引擎。可是关于 JSI 而言,它与引擎彻底解耦,理论上能够在任何 JS 引擎(比方 V8、Hermes)上运用。
JSI 又是怎么让 JS 能够直接调用到 Native 的呢?
Native 办法经过 C++ 宿主目标露出给 JS。经过 JSI 接口,JS 目标能够直接引用 C++ 目标,并调用到它所露出的接口。反之,C++ 目标也能够直接引用并调用 JS 目标的办法。
总而言之,JSI 完结了 JS 目标 与 Native 目标间的同步调用,一起也处理了音讯传递需求序列化和反序列化的问题。
一起 JSI 还有另一大优点,它是用 C++ 编写的,凭借 C++ 的强大功用,在未来 React Native 也能够在其他体系上运转,比方智能电视、智能穿戴设备等等。
新旧烘托器比照
旧架构的烘托器
旧架构的烘托器是 UI Manager,当咱们履行页面烘托时,它是这么运转的:
- React 在 JS 侧会依据代码创立一个 ReactElementTree
- 烘托器会依据 ReactElementTree 在 C++ 层创立一个 ReactShadowTree
- 布局引擎(比方 Yoga)会处理这个 ReactShadowTree 并计算出元素的布局方位
- 处理完结后,ShadowTree 会被转换成由 Native 组件构成的 HostViewTree(比方 View 组件会被转换成 Native 的 ViewGroup 组件)
因为旧架构中通讯都是要经过 JSBridge 的,因而旧架构的烘托器也会存在转换慢以及重复数据等问题。一起因为通讯非同步,会存在前面说到的烘托堵塞问题。
新架构的烘托器 —— Fabric
Fabric 是 RN 在新架构中提出的新一代烘托器。
Fabric 凭借了 JSI 的才能,能够做到 JS 线程 和 UI 线程之间的同步通讯。这关于用户体会是有极大的提升的。
比方用户在翻滚列表 / 操作手势时,这些行为都能够同步的反馈给用户,而不再像曾经那样或许会出现堵塞现象。
另外,新的 Shadow Tree 会在 JS 线程 和 UI 线程之间共享,运训来自两端都的直接交互。
新旧 NativeModules 比照
旧架构的 NativeModules
在旧架构中,一切 NativeModules 在 App 启动时都需求被初始化:
- 首先 Native 开发者先定义好接口,然后把 NativeModules 注册进一个 Module 列表中
- RN 在启动时,会把一切的 Modules 初始化,并生成一份映射表,这份映射表会被注入到 C++ 层和 JS 层
- 这样,在 Native 层、C++ 层和 JS 层都存在同一份映射表,JS 能够经过 JSBridge 调用映射表中对应的 Native 办法
旧架构存在一个很显着的问题:即运用户或许永久不会运用到某个 NativeModules,这个 Module 还是会在运用已启动时就被初始化。这有或许会影响到运用的启动时刻
新架构的 NativeModules —— TurboModules
新架构的 NativeModules 叫做 TurboModules:
- JS 层首先定义好 Module 的接口(即上面说到的 Static Types),能够用 Typescript 定义
- RN 经过 CodeGen 会生成该接口对应的各个平台的 Native 接口,Native 侧只需求继承这个接口去做详细的完结即可
- 因为凭借了 JSI 的才能,RN 能够做到只有当 JS 调用到某个 Module 时,才去履行它的初始化,做到真正的模块懒加载
CodeGen
JS 是一种动态类型言语,可是 JSI 是根据 C++ 的, C++ 是一种静态类型言语。
为了确保二者之间能够顺畅的通讯,新架构中引入了静态类型查看器 —— CodeGen。
CodeGen 运用 JS 的类型定义(比方 Typescript)作为声明来源,来生成 Fabric 和 TurboModules 所运用的接口元素。一起 CodeGen 还能够在构建时生成对应的 Native 代码,削减运转时的开销。
总结
RN 新架构比照旧架构有几个要害的改变:
- 运用 JSI 代替 JSBridge
- 运用 Fabric 代替 UI Manager,更像 Web 端的烘托体系
- 运用 TurboModules 代替 NativeModules,支撑 Native 模块懒加载
- 支撑任何 JS 引擎上运转的潜力
- 支撑同步通讯
- 支撑兼容 JS 和 Native 之间的静态类型查看
参考
- reactnative.dev/docs/next/t…
- medium.com/coox-tech/d…