个人前言

熟悉我的人应该知道,虽然现在我一直主力于 Flutter, 但是 GSY App 系列项目最早其实是 React Native , 之后才是 WeexFlutter所以其实我对 RN 一直有着“初恋”的情节,基本上是它带着我走进前端和跨平台的领域,而恰巧最近看到了关于它的消息,就顺便了解下多年后它又有什么升级。

直到目前为止,React Native 的版本号是 0.67 ;我看了眼两年没更新的 GSYGithubApp ,用的 React Native 的版本号是 0.61 ,两年里从 61 升级到了 67 ,看来 RN 1.0 正式版这个梗还能继续玩下去。

正文

内容参考: https://medium.com/coox-tech/deep-dive-into-react-natives-new-architecture-fb67ae615ccd

随着 RN 团队关于 深入了解 React Native 的新架构 文章的发布,这次新架构带来的调整主要在于以下四点:

    1. JavaScript Interface(JSI)
    1. Fabric
    1. Turbo Modules
    1. CodeGen

在 RN App 里,所有的 JS 代码都会打包成一个 JS Bundle 文件保存在本地运行,当 RN App 运行时,一般会有三个线程:

  • 1、 JavaScript 线程:属于 JS 引擎,用于运行 JS Bundle ;
  • 2、 Native/UI 线程:运行 Native Modules 和处理 UI 渲染、用户手势等操作;
  • 3、 Shadow 线程:在渲染之前计算元素的布局;

在 RN 里 JS 线程和 Native 线程之前是通过 bridge 来交互,而交互的数据必须被转化为 JSON,而这个桥只能处理异步通信。

JavaScriptCore:JavaScript 引擎,React Native 用它执行 JS 代码;

Yoga:布局引擎,计算UI位置;

一、JavaScript Interface (JSI)

目前 RN 使用 Bridge Module 来让 JS 和 Native 线程进行通信,每次利用 Bridge 发送数据时,都需要转换为 JSON, 而收到数据时也需要进行解码。

这就意味着 JavaScript 和 Native 直接是隔离的,也就是 JS 线程不能直接调用 Native 线程上的方法

另一个就是;通过 Bridge 发送的消息本质上是异步的,如果需要 JS 代码和 Naitve 同步执行在之前是无法实现。

例如,如果 JS 线程需要访问 native modules(例如蓝牙),它就需要向 native 线程发送消息,JS 线程就会通过 Bridge 发送一个 JSON 消息,然后消息在 native 线程上进行解码,最终将执行所需的 native 代码。

而在全新架构中,Bridge 将被一个名为 JavaScript Interface 的模块所代替,它是一个轻量级的通用层,用 C++ 编写,JavaScript Engine 可以使用它直接执行或者调用 native。

通用层代表着:JSI 让 JavaScript 接口将与 Engine 分离,这意味着新架构支持 RN 直接使用其他 JavaScript 引擎,比如 Chakrav8Hermes 等等

那 JSI 如何让 JavaScript 直接调用到原生方法?

在 JSI 里 Native 方法会通过 C++ Host Objects 暴露给 JS, 而 JS 可以持有对这些对象的引用,并且使用这些引用直接调用对应的方法

这就类似于 Web 里 JS 代码可以保存对任何 DOM 元素的引用,并在它上面调用方法:

const container = document.createElement(‘div’);

举个例子,在这里的 container 会包含一些在 C++ 中初始化的 DOM 元素的引用,这时候如果我们调用 container 上的任何方法,它就会调用 DOM 元素上的方法。

JSI 就是以类似的方式运行,JSI 将允许 JS 代码保存对 Native Modules 的引用,并且 JS 可以直接通过引用去调用 Native 上的方法。

总结起来就是:

  • JSI 将支持其他 JS 引擎
  • JSI 允许线程之间的同步相互执行,不需要 JSON 序列号等耗费性能的操作
  • JSI 是用 C++ 编写,以后如果针对电视、手表等其他系统,也可以很方便地移植

二、Fabric

Fabric 是新的渲染系统,它将取代当前的 UI Manager。

在 Fabric 之前,当 App 运行时,React 会执行你的代码并在 JS 中创建一个 ReactElementTree ,基于这棵树渲染器会在 C++ 中创建一个 ReactShadowTree

UI Manager 会使用 Shadow Tree 来计算 UI 元素的位置,而一旦 Layout 完成,Shadow Tree 就会被转换为由 Native Elements 组成的 HostViewTree(例如:RN 里的 会变成 Android 中的 ViewGroup 和 iOS 中的 UIView)。

而之前线程之间的通信都发生在 Bridge 上,这就意味着需要在传输和数据复制上耗费时间。

例如如果一个 ReactElementTree 节点恰好是一个 <Image/>,那么 ReactShadowTree 的节点也会是一个图像,但是这些数据必须被复制并分别存储在两个节点中。

另外由于 JS 和 UI 线程不同步,因此在某些情况下 App 可能会因为丢帧而显得卡顿(例如滚动有大量数据的 FlatList

而得益于前面的 JSI, JS 可以直接调用 Native 方法,其实就包括了 UI 方法,所以 JS 和 UI 线程可以同步执行从而提高列表、跳转、手势处理等的性能

使用新的 Fabric 渲染,用户交互(如滚动、手势等)可以优先在主线程或 Native 线程中同步执行,而 API 请求等其他任务使用异步执行。

另外新的 Shadow Tree 将成为 immutable,它会在 JS 和 UI 线程之间共享,以两端进行直接交互

在以前 RN 必须维护两个层次结构的 DOM 节点,但因为现在 Shadow Tree 可以共享,在减少内存消耗的部分也会得到相应的优化。

三、Turbo Modules

在之前的架构中 JS 使用的所有 Native Modules(例如蓝牙、地理位置、文件存储等)都必须在应用程序打开之前进行初始化,这意味着即使用户不需要某些模块,但是它仍然必须在启动时进行初始化。

Turbo Modules 基本上是对这些旧的 Native 模块的增强,正如在前面介绍的那样,现在 JS 将能够持有这些模块的引用,所以 JS 代码可以仅在需要时才加载对应模块,这样可以将显着缩短 RN 应用的启动时间

四、Codegen

Codegen 主要是用于保证 JS 代码和 C++ 的 JSI 可以正常通信的静态类型检查器,通过使用类型化的 JS 作为参考来源,CodeGen 将定义可以被 Turbo 模块和 Fabric 使用的接口,另外 Codegen 会在构建时生成 Native 代码,减少运行时的开支。

从上面四点可以看到 2022 年 RN 将迎来性能和体验上的跃迁,本次即将到来的全新架构将解决 RN 多年以后被人诟病的各种根本上的设计问题

Skia

另外还要介绍的内容就是 react-native-skia ,目前它还处于 alpha release 的阶段,但是它也给 RN 带来的新的可能。

众所周知,Flutter 跨平台的性能提升和解耦来自于直接使用 Skia 渲染而非系统控件,而如今 RN 也有类似的支持。

react-native-skia 需要 react-native@>=0.66 的支持,而目前它上面的操作都还是十分原始的 canvas 行为,例如通过 Circle 绘制圆形,通过 blendMode 配置重叠模式等。

import {Canvas, Circle, Group} from "@shopify/react-native-skia";export const HelloWorld = () => {const width = 256;const height = 256;const r = 215;return (<Canvas style={{ flex: 1 }}><Group blendMode="multiply"><Circle cx={r} cy={r} r={r} color="cyan" /><Circle cx={width - r} cy={r} r={r} color="magenta" /><Circlecx={width/2}cy={height - r}r={r}color="yellow"/></Group></Canvas>);
};

当然它也支持直接使用 SkiaView ,然后通过 canvas 来绘制你需要的图形:

import {Skia, BlendMode, SkiaView, useDrawCallback} from "@shopify/react-native-skia";const paint = Skia.Paint();
paint.setAntiAlias(true);
paint.setBlendMode(BlendMode.Multiply);export const HelloWorld = () => {const width = 256;const height = 256;const r = 215;const onDraw = useDrawCallback((canvas) => {// Cyan Circleconst cyan = paint.copy();cyan.setColor(Skia.Color("cyan"));canvas.drawCircle(r, r, r, cyan);// Magenta Circleconst magenta = paint.copy();magenta.setColor(Skia.Color("magenta"));canvas.drawCircle(width - r, r, r, magenta);// Yellow Circleconst yellow = paint.copy();yellow.setColor(Skia.Color("yellow"));canvas.drawCircle(width/2, height - r, r, yellow);});return (<SkiaView style={{ flex: 1 }} onDraw={onDraw} />);
};

目前该库支持 Image、Text、Shader、Effects、Shapes、Animations 等操作,而事实上该库的实现和 Flutter 很是相似,比如:

在 Android 上的 SkiaDrawView 其实就是 TextureView ,绘制逻辑是作者自己写的 reactskia 上,这里只是借助了 TextureViewsurfaceTouchEvent 等的支持。

如下图所示,是关于使用 react-native-skia 实现的一段 Demo ,详细可见: https://shopify.github.io/react-native-skia/

可以预见目前的 react-native-skia 还有不少问题需要解决,但是它让 RN 可以更高效地使用丰富的 Canvas 能力,对于 RN 的未来而言不免是一次不错的尝试。

2022 年 React Native 的全新架构更新相关推荐

  1. React Native之旅—热更新(Pushy)

    React Native(以下简称 RN)最吸引我的主要有三点:跨平台.性能良好.热更新,在体验了良好的性能和跨平台的便利之后,我便迫不及待的开始捣鼓热更新. 搜索了一圈回来发现,目前提供完整RN热更 ...

  2. React Native集成CodePush热更新

    作为一款以JavaScript语音为基础跨平台开发框架,React Native本身已经具备了动态更新的能力,不过官方却没有提供一套标准的动态更新方案.因为一个标准的动态更新方案,除了需要客户端具备动 ...

  3. iOS端实现React Native差异化增量更新

    作为一名iOS原生开发工程师,通过一个礼拜的面试之后发现,原来并不想学的react-native真的是火的一塌糊涂,坐标:杭州,很多公司招聘iOS开发除了原来的OC和Swift,多了一门新语言:rea ...

  4. RN:React Native原理以及新架构JSI、Fabric等概念

    说明 RN需要一个JS的运行环境, 在IOS上直接使用内置的javascriptcore, 在Android 则使用webkit.org官方开源的jsc.so. 此外还集成了其他开源组件,如fresc ...

  5. 庖丁解牛!深入剖析React Native下一代架构重构

    Facebook在2018年6月官方宣布了大规模重构React Native的计划及重构路线图.目的是为了让React Native更加轻量化.更适应混合开发,接近甚至达到原生的体验.(也有可能是Re ...

  6. React Native热更新方案

    随着 React Native 的不断发展完善,越来越多的公司选择使用 React Native 替代 iOS/Android 进行部分业务线的开发,也有不少使用 Hybrid 技术的公司转向了 Re ...

  7. React Native 热更新方案

    转载: https://blog.csdn.net/xiangzhihong8/article/details/73201421 随着 React Native 的不断发展完善,越来越多的公司选择使用 ...

  8. 基于 React Native 的 58 同城 App 开发实践

    作者简介: 彭飞,58 同城 iOS 客户端架构师.专注于新技术的研发,主要负责 App 端组件化架构以及性能优化,并已推广 React Native 在 58 同城 App 中业务场景的应用.在 M ...

  9. React Native Android 从学车到补胎和成功发车经历

    [工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 好几个月没发车了,完全生疏了,为了接下来能持续性的发好车,这次先准 ...

  10. 最火移动端跨平台方案盘点:React Native、weex、Flutter

    本文原文由"恋猫月亮"原创发布,原题为<移动端跨平台开发的深度解析>,本次重新整理后,为了优化阅读体验,内容略有改动,感谢原作者的无私分享. 1.前言 跨平台一直是老生 ...

最新文章

  1. Swift 3.0封装 URLSession 的GET/SET方法代替 Alamofire
  2. ndarray对象的建立
  3. qt创建右键菜单,显示在鼠标点击处
  4. 【LeetCode】【HOT】301. 删除无效的括号(递归)
  5. python如何搜索关键字_Python遍历目录和搜索文件中的关键字
  6. 【clickhouse】MergeTree引擎的固定/自适应索引粒度
  7. java 初始化duration_JAVA 8 DURATION 详解
  8. java中虚拟机命令:jstack使用方法
  9. 十个让你变成糟糕的程序员的行为
  10. int main():声明指定了两个以上的数据类型
  11. Xshell 6免费版
  12. 本地邮件服务器 易邮 使用
  13. 生活中常用的汉字?有4600个。都有哪些呢?
  14. [python] ylgy攻略 用魔法打败魔法
  15. FAT文件系统解析(一) 引导扇区、FAT表及根目录区分析
  16. grub rescue救援模式的处理
  17. x3650m3服务器如何安装系统,IBM X3650 M3服务器安装windows 2003的方法
  18. 11.0、C语言数据结构——栈
  19. qq令牌64位密钥提取_QQ令牌工具 活令牌查询动态密码(大哥牌)
  20. 【有利可图网】PS教程:制作棱形岩石文字海报图片

热门文章

  1. dos从优盘启动计算机,对老旧电脑升级很重要,教你制作纯DOS的U盘启动盘
  2. roc曲线spss怎么做_如何用SPSS做ROC曲线分析?看这1篇就够了!
  3. 为什么我卸载了微博?
  4. eclipse 中用svn共享项目
  5. 基于Java实现的毕业设计论文选题系统
  6. SEO快速排名,关键词快速排名软件,到底靠谱不靠谱
  7. 给出直角三角形斜边,求有多少三角形符合要求
  8. Linux虚拟机下载和安装简单流程
  9. 3个传教士与3个野人,哥带你们过河去
  10. 打印纸张尺寸换算_各种打印纸的尺寸是多少?