React Native是一个优秀的跨平台移动应用解决方案,可以让你轻松地使用React(和JavaScript)来创建native移动应用程序。 React Native 需要使用 JavaScript 引擎执行 JavaScript 代码,包括 JavaScriptCore、Hermes、V8。
随着Flutter等新框架的崛起,React Native正经受着越来越大的挑战,RN性能上的瓶颈愈发明显。为了在与Flutter等框架的对抗中保持竞争力, RN在架构上也进行了一次非常大的升级。
原有架构及问题
一共分四个部分:- 用户编写的React代码
- React代码转换之后的js
- The Bridge
- Native side
原有架构最大的问题:
- 组件和 API
太过依赖 JSBridge 的初始化
,而且通讯能力也局限于这一条通道。 - JS和Native之间并不真正直接通信,它们的通信依赖于
跨Bridge传输的异步JSON消息
。
它们之间传递的信息,都要序列化为JSON之后进行异步传输。这样就造成一个比较常见的性能问题,比如快速滑动ListView的时候会白屏。 因为 JSBridge 的异步关系导致了 shadow 层最终呈现到原生的 UI 是异步的,而且滑动太快后会有大量的 UI 事件会阻塞在 JSBridge。
UI 的渲染过程分为三层:JS 业务层、shadow tree、原生 UI 层
。
其中 JS 和 shadow tree 是通过 JSBridge 来同步数据的,JS 层会将所有 UI node 生成一串 JSON 数据,传递到原生 shadow 层,原生 shadow 层通过传入 node 数据,新增新 UI 或者删除一些不需要的 UI 组件。
从渲染的层次来看,React Native 是多线程运行的,最常见的是 JS 线程和原生端的线程,一旦线程间异常,JSBridge 整体将会阻塞,我们经常也能看到 JS 运行异常了,实际 JS 线程已经无响应了,但原生端还能响应滚动事件。
新架构与解决方法
RN 在 0.59 版本使用 JSI 取代了先前的 JSBridge
。
新架构将bridge分为两部分:
- Fabric,新架构的UI manager
- TurboModules,这个与native端交互的新一代实现
JSI是一个精简通用型的JS引擎接口,理论上可以对接任何JS引擎,包括Google的V8和微软的ChakraCore,或者是RN现在使用的JavaScriptCore(JSC)的新版本(JSI已经集成到RN的0.59版本中,并且在该版本中升级了JSC的版本)。
新架构核心的优势:
- JSI是架起 JS 和Native之间的桥梁,通过在C++层实现一个 JSI::HostObject,现在
不需要序列化成JSON
并双向传递等一系列操作,实现了Native和 JS间的直接同步通讯
。
通过使用JSI,Fabric将UI操作作为函数公开给JavaScript,新的Shadow Tree(决定在屏幕上真正显示的内容)在两个领域之间共享,允许两端直接交互。
新架构下UI渲染以及如何解决快速滑动过程中的白屏问题的(实线是同步,虚线是异步):
- 初始化:JS 到 Shadow 层已经是同步操作了,而 shadow 层到原生 UI 变成了可以异步也可以同步操作了,组件可以根据自己的业务场景来适配不同的操作。
- 滑动过程:原生端直接控制 JS 层渲染,同时创建 shadow 层的 node 节点,node 节点会采用同步的方式渲染原生 UI,整个过程中滑动的渲染是采用的同步操作,所以不会出现旧架构下白屏的问题。
JSI 的另一优势是它抹平了 JavaScript 引擎的差异。使用 JSI,我们不必关心底层是Hermes 引擎还是 JavaScriptCore 引擎,JSI 底层都消化了。因此只需要基于 JSI 的接口编写即可。
JS引擎
在使用React Native时,你的JavaScript代码将会运行在两个不同的环境上:
- 在iOS、Android的模拟器或是真机上,React Native使用的是
JavaScriptCore
,也就是Safari所使用的JavaScript引擎。但是在iOS上JavaScriptCore并没有使用即时编译技术(JIT),因为在iOS中应用无权拥有可写可执行的内存页(因而无法动态生成代码)。 - 在使用Chrome调试时,所有的JavaScript代码都运行在Chrome中,并且通过WebSocket与原生代码通信。此时的运行环境是
V8引擎
。 - Facebook推出了新一代JavaScript执行引擎Hermes。
Hermes
是一款小巧轻便的 JavaScript 引擎,专门针对在 Android 上运行 React Native 进行了优化。
对于许多应用程序,只需启用 Hermes 即可缩短启动时间、减少内存使用量并缩小应用程序大小,此外因为它采用 JavaScript 标准实现,所以很容易在 React Native 应用中集成。
开启Hermes,首先需要确保至少使用 React Native 0.60.2 以上的版本。
编辑 android/app/build.gradle 文件并进行以下更改:
project.ext.react = [
entryFile: "index.js",
- enableHermes: false // clean and rebuild if changing
+ enableHermes: true // clean and rebuild if changing
]
复制代码