likes
comments
collection
share

【uni-app&微信小程序&React Native】跨端原理初探

作者站长头像
站长
· 阅读数 11

文章内容

  1. 以官方文档为基础,对uni-app的基础框架(逻辑层、渲染层)、组件、API进行简单地分析
  2. 以官方文档为基础,对微信小程序框架(逻辑层、视图层)、运行时进行简单地分析
  3. 以官方文档为基础,对React Native旧架构和新架构进行简单地分析

1. uni-app编译

  • 在web平台,将.vue文件编译为js代码。与普通的vue cli项目类似
  • 在微信小程序平台,编译器将.vue文件拆分生成wxml、wxss、js等代码
  • 在app平台,将.vue文件编译为js代码。进一步,如果涉及uts代码:
    • 在Android平台,将.uts文件编译为kotlin代码
    • 在iOS平台,将.uts文件编译为swift代码

编译器分vue2版和vue3版

  • vue2版:基于webpack实现
  • vue3版:基于Vite实现,性能更快

编译器支持条件编译,即可以指定某部分代码只编译到特定的终端平台。从而将公用和个性化融合在一个工程中。

2. uni-app运行时runtime

2.1 基础框架

  • 在web和小程序上,不需要uni-app提供js引擎和排版引擎,直接使用浏览器和小程序的即可。但app上需要uni-app提供
  • App的js引擎:App-Android上,uni-app的js引擎是v8,App-iOS是jscore
  • App的渲染引擎:同时提供了2套渲染引擎,.vue页面文件由webview渲染,原理与小程序相同;.nvue页面文件由原生渲染,原理与react native相同。开发者可以根据需要自主选择渲染引擎。

uni-app App 端内置了一个基于 weex 改进的原生渲染引擎,提供了原生渲染能力

  • 在 App 端,如果使用 vue 页面,则使用 webview 渲染
  • 如果使用 nvue 页面(native vue 的缩写),则使用原生渲染
  • 一个 App 中可以同时使用两种页面,比如首页使用 nvue,二级页使用 vue 页面,hello uni-app 示例就是如此

虽然 nvue 也可以多端编译,输出 H5 和小程序,但 nvue 的 css 写法受限,所以如果你不开发 App,那么不需要使用 nvue。

2.1.1 逻辑层和渲染层分离

在web平台,逻辑层(js)和渲染层(html、css),都运行在统一的webview里。但在小程序和app端,逻辑层和渲染层被分离了。

分离的核心原因是性能。过去很多开发者吐槽基于webview的app性能不佳,很大原因是js运算和界面渲染抢资源导致的卡顿。

不管小程序还是app,逻辑层都独立为了单独的js引擎,渲染层仍然是webview

app上也支持纯原生渲染,使用.nvue文件

2.1.2 逻辑层详解

逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Android4.4上跑es6代码,另一方面,它无法运行window、document、navigator、localstorage等浏览器专用的js API。

jscore就是一个标准js引擎,标准js是可以正常运行的,比如if、for、各种字符串、日期处理等。js和浏览器的区别要注意区分开来。

【uni-app&微信小程序&React Native】跨端原理初探

  • 所谓浏览器的js引擎,就是jscore或v8的基础上新增了一批浏览器专用API,比如dom;
  • node.js引擎,则是v8基础上补充一些电脑专用API,比如本地io;
  • 那么uni-app的App端和小程序端的js引擎,其实是在jscore上补充了一批手机端常用的JS API,比如扫码。

2.1.3 渲染层详解

h5和小程序平台,以及app-vue,视图层是webview,即.vue文件都会被渲染为WebView

app-nvue的视图层是基于weex改造的原生渲染视图,即.nvue文件会被改造为APP原生组件

兼容性

在iOS上,只能使用iOS提供的Webview(默认是WKWebview)。它有一定的浏览器兼容问题,iOS版本不同,它的表现有细微差异(一般可忽略)。

在Android上,小程序大多自带了一个几十M的chromium webview,而App端没办法带这么大体积的三方包,因此uni-app默认使用了Android system webview,这个系统webview跟随手机不同而有差异

在Android上,App端也支持使用腾讯X5引擎,这样就统一版本,尽可能减少兼容性问题

2.1.4 逻辑层和渲染层小结

逻辑层: js基本没有不同手机的兼容问题(因为js引擎自带了)

渲染层: 在app-vue上使用系统webview时会有手机浏览器的css兼容问题。此时或者不要用太新的css语法,或者集成腾讯x5引擎。

2.1.5 逻辑层和渲染层分离的利与弊

逻辑层和视图层分离,好处是js运算不卡渲染,最简单直接的感受就是:窗体动画稳。

如果开发者使用过App,应该有概念,webview新窗体一边做进入动画,一边自身渲染,很容易卡动画。而uni-app则无需写预载代码,新窗体渲染快且动画稳定。

但是两层分离也带来一个坏处,这两层互相通信,其实是有损耗的。

iOS还好,但Android低端机上,每次通信都要耗时几十毫秒。平时看不出来影响,但有几个场景表现明显:

  1. 连续高帧率绘制canvas动画,会发现还不如webview内部绘制流畅
  2. 视图层滚动、跟手操作,不停反馈给逻辑层,js再处理逻辑并通知视图层做对应更新。此时会发现交互不跟手或卡顿

不管小程序还是app,不管app-vue还是app-nvue,都有这个两层通信损耗的问题。

2.1.6 逻辑层和渲染层分离后进行的性能提升方法

在webview中,提供了一种运行于视图层的专属js,微信叫做wxs。uni-app支持把wxs编译到微信小程序、App和H5中,而且在wxs的基础上进行增强:

  • 微信里对wxs限制较多,只能实现有限的功能。
  • app端提供了更强大的renderjs,并兼容到H5平台,比如canvas动画,微信的canvas无法通过wxs操作,js不停绘制canvas动画因通信折损而无法流畅。uni-app的app-vue里的canvas对象设计在webview视图层的,通过renderjs可以在视图层直接操作canvas动画,将不再有通信折损,实现更流畅的效果

在原生渲染的视图层(app-nvue),逻辑层和视图层的折损一样存在。包括react native也有这个问题,weex提供了一套bindingx机制,可以在js里一次性传一个表达式给原生层,由原生层解析后根据指令操作原生的视图层,避免反复跨层通信。这个技术在uni-app里也可以使用。

bindingx作为一种表达式,它的功能不及js强大,但手势监听、动画还是可以实现的,比如uni ui的swiperAction组件在app-nvue下运行时会自动启用bindingx,以实现流畅跟手。

2.2 组件

为了降低开发者的学习成本,uni-app的内置基础组件命名规范与小程序基本相同。

runtime中包括的组件只有基础组件,如、等。为了减少包体积,扩展组件不包含在uni-app的runtime中,而是下载到用户的项目代码中(这些组件都是vue组件),让用户自己按需使用这些扩展组件

在小程序端,uni-app基础组件会直接转义为小程序自己的内置组件。在小程序的runtime中不占体积。在web和android、iOS端,这几十个组件都在uni-app的runtime中,会占用一定体积,相当于内置了一套ui库。

2.3 API

主要分为:

  • 小程序平台:uni对象会转为小程序的自有对象,比如在微信小程序平台,编写uni.request等同于wx.request。那么所有wx.的API都可以这样使用。
  • web平台:window、dom等浏览器专用API仍可以使用
  • app平台:除了uni.的API,还可以使用plus.的APINative.js,以及通过uts编写原生插件,或者使用java和objectC编写原生插件。这些原生插件调用os的API并封装给js使用。

uni-app不限制各端原生平台的API调用。开发者可以在uni-app框架中无限制的调用该平台所有能使用的API。即,

  • 在小程序平台,小程序的所有API都可以使用;
  • 在web平台,浏览器的所有API都可使用;
  • 在iOS和Android平台,os的所有API都可以使用。

在上面的2.1 基础框架的分析中,我们知道 App的渲染提供了2套渲染引擎:

  • .vue页面文件由webview渲染,原理与小程序相同
  • .nvue页面文件由原生渲染,原理与react native相同

接下来我们将针对小程序和react native的原理展开分析


3. 微信小程序底层原理

3.1 框架

整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXMLWXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

小程序采用 AppService 和 WebView 的双线程模型,渲染层的界面使用 WebView 进行渲染;逻辑层采用 JSCore 运行 JavaScript 代码 基于 WebView 和原生控件混合渲染的方式,小程序还优化扩展了 Web 的基础能力,保证了在移动端上有良好的性能和用户体验

Skyline渲染引擎Beta

Skyline渲染引擎了解下即可,目前还处于测试阶段,本文还是将重点放在WebView模式下

Web 技术至今已有 30 多年历史,作为一款强大的渲染引擎,它有着良好的兼容性和丰富的特性。 尽管各大厂商在不断优化 Web 性能,但由于其繁重的历史包袱和复杂的渲染流程,使得 Web 在移动端的表现与原生应用仍有一定差距。为了进一步优化小程序性能,提供更为接近原生的用户体验,微信小程序在 WebView 渲染之外新增了一个渲染引擎 Skyline,其使用更精简高效的渲染管线,并带来诸多增强特性,让 Skyline 拥有更接近原生渲染的性能体验。

在 Skyline 环境下,Skyline 创建了一条渲染线程来负责 Layout, Composite 和 Paint 等渲染任务,并在 AppService 中划出一个独立的上下文,来运行之前 WebView 承担的 JS 逻辑、DOM 树创建等逻辑。这种新的架构相比原有的 WebView 架构,有以下特点:

  • 界面更不容易被逻辑阻塞,进一步减少卡顿
  • 无需为每个页面新建一个 JS 引擎实例(WebView),减少了内存、时间开销
  • 框架可以在页面之间共享更多的资源,进一步减少运行时内存、时间开销
  • 框架的代码之间无需再通过 JSBridge 进行数据交换,减少了大量通信时间开销

Skyline渲染引擎能很好地保持和原有架构的兼容性,基于 WebView 环境的小程序代码基本上无需任何改动即可直接在新的架构下运行。但是WXS 被移到 AppService 中,虽然逻辑本身无需改动,但询问页面信息等接口会变为异步,效率也可能有所下降;为此,我们同时推出了新的 Worklet 机制,用以高性能地构建各种复杂的动画效果。

新的渲染流程如下图所示:【uni-app&微信小程序&React Native】跨端原理初探

3.1.1 逻辑层

小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发 JavaScript 代码的运行环境以及微信小程序的特有功能。逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。

JavaScript 的基础上,微信小程序增加了一些功能,以方便小程序的开发:

  • 增加 AppPage 方法,进行程序注册页面注册
  • 增加 getAppgetCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 提供模块化能力,每个页面有独立的作用域

注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等。

3.1.2 视图层

框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。

  • WXML(WeiXin Markup language) 用于描述页面的结构。
  • WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
  • WXSS(WeiXin Style Sheet) 用于描述页面的样式。
  • 组件(Component)是视图的基本组成单元。

3.1.3 双线程模型架构

小程序的逻辑层和渲染层是分开的两个线程。在渲染层,宿主环境会把WXML转化成对应的JS对象,在逻辑层发生数据变更的时候,我们需要通过宿主环境提供的setData方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的Dom树上,渲染出正确的UI界面

由于WebView 的 JS 逻辑、DOM 树创建、CSS 解析、样式计算、Layout、Paint (Composite) 都发生在同一线程。在 WebView 上执行过多的 JS 逻辑可能阻塞渲染,导致界面卡顿。

【uni-app&微信小程序&React Native】跨端原理初探小程序逻辑层和渲染层的通信会由 Native (微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。

为什么要使用Hybrid技术来渲染微信小程序呢?

一般来说,渲染界面的技术有三种:

  1. 用纯客户端原生技术来渲染
  2. 用纯 Web 技术来渲染
  3. 介于客户端原生技术与 Web 技术之间的,互相结合各自特点的技术(下面统称 Hybrid 技术)来渲染

由于小程序的宿主是微信,所以不太可能用纯客户端原生技术来编写小程序 。如果这么做,那小程序代码需要与微信代码一起编包,跟随微信发版本,这种方式跟开发节奏必然都是不对的。因此,微信小程序需要像Web 技术那样,有一份随时可更新的资源包放在云端,通过下载到本地,动态执行后即可渲染出界面。

但是,如果微信小程序用纯 Web 技术来渲染小程序,在一些有复杂交互的页面上可能会面临一些性能问题,这是因为在 Web 技术中,UI渲染跟 JavaScript 的脚本执行都在一个单线程中执行,这就容易导致一些逻辑任务抢占UI渲染的资源。

因此,最终选择了两者结合起来的 Hybrid 技术来渲染小程序。

Hybrid 技术在业界过去几年里演化过数种技术方案:典型的如早期的PhoneGap,还有近几年流行的React Native(下称 RN),还有像微信网页里的 JS-SDK这种轻量级的应用

为什么要不使用React Native这样技术作为微信小程序的技术选型呢?

微信小程序最终没有选择类RN作为微信小程序的技术选型,那是因为:

  1. RN 所支持的样式是 CSS 的子集,会满足不了 Web 开发者日渐增长的需求,而对 RN 的改造具有不小的成本和风险。
  2. RN 现有能力下还存在的一些不稳定问题,比如性能、Bug等。RN 是把渲染工作全都交由客户端原生渲染,实际上一些简单的界面元素使用 Web 技术渲染完全能胜任,并且非常稳定。
  3. RN 存在一些不可预期的因素,比如近期就出现了许可协议问题。

因此微信小程序最终选择了类似于微信 JSSDK 这样的 Hybrid 技术,即界面主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力:

  • 每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重
  • 界面渲染定义了一套内置组件以统一体验,并且提供一些基础和通用的能力
  • 内置组件有一部分较复杂组件是用客户端原生渲染的,以提供更好的性能

3.1.4 组件系统

视图层的组件系统

小程序的视图是在WebView里渲染的,那搭建视图的方式自然就需要用到HTML语言。如果我们直接提供HTML的能力,那前面章节所介绍的为解决管控与安全而建立的双线程模型就成为摆设了。开发者可以利用A标签实现跳转到其它在线网页,也可以动态执行JavaScript等。除管控与安全外,还有一些的不足之处:

  • 标签众多,增加理解成本;
  • 接口底层,不利于快速开发;
  • 能力有限,会限制小程序的表现形式。

因此,微信小程序设计一套组件框架——Exparser。基于这个框架,内置了一套组件,以涵盖小程序的基础功能,便于开发者快速搭建出任何界面。同时也提供了自定义组件的能力,开发者可以自行扩展更多的组件,以实现代码复用。

3.1.5 原生组件

在内置组件中,有一些组件较为特殊,它们并不完全在Exparser的渲染体系下,而是由客户端原生参与组件的渲染,这类组件我们称为“原生组件”,这也是小程序Hybrid技术的一个应用。引入原生组件主要有3个好处:

  1. 扩展Web的能力。比如像输入框组件(input, textarea)有更好地控制键盘的能力。
  2. 体验更好,同时也减轻WebView的渲染工作。比如像地图组件(map)这类较复杂的组件,其渲染工作不占用WebView线程,而交给更高效的客户端原生处理。
  3. 绕过setData、数据通信和重渲染流程,使渲染性能更好。比如像画布组件(canvas)可直接用一套丰富的绘图接口进行绘制。

常用的原生组件有:video、map、canvas、picker

交互比较复杂的原生组件都会提供“context”,用于直接操作组件。以canvas为例,小程序提供了wx.createCanvasContext方法来创建canvas的context。这是一个可以用于操作canvas的对象,对象下提供了很多绘图的方法,如“setFillStyle”方法可以设置填充样式,“fillRect”方法用于绘制矩形

原生组件脱离在WebView渲染流程外,这带来了一些限制。最主要的限制是一些CSS样式无法应用于原生组件,例如,不能在父级节点使用overflow:hidden来裁剪原生组件的显示区域;不能使用transformrotate让原生组件产生旋转等

3.2 运行时

微信小程序运行在多种平台上:iOS/iPadOS 微信客户端、Android 微信客户端、Windows PC 微信客户端、Mac 微信客户端、小程序硬件框架和用于调试的微信开发者工具等。

不同运行环境下,脚本执行环境以及用于组件渲染的环境是不同的,性能表现也存在差异:

  • 在 iOS、iPadOS 和 Mac OS 上,小程序逻辑层的 JavaScript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS 14、iPad OS 14、Mac OS 11.4 等;
  • 在 Android 上,小程序逻辑层的 JavaScript 代码运行在 V8 中,视图层是由基于 Mobile Chromium 内核的微信自研 XWeb 引擎来渲染的;
  • 在 Windows 上,小程序逻辑层 JavaScript 和视图层都是用 Chromium 内核;
  • 在 开发工具上,小程序逻辑层的 JavaScript 代码是运行在 NW.js 中,视图层是由 Chromium Webview 来渲染的。

3.2.1 JavaScript 支持情况

  • 小程序中不支持动态执行 JS 代码,即使用 eval 执行 JS 代码或者使用new Function创建函数
  • 标准 ECMAScript 支持,微信小程序内置了一份 core-jsPolyfill。core-js 可以将平台环境缺失的标准 API 补齐。

需要注意的是,平台对 ECMAScript 语法的支持差异无法抹平,当你需要使用一些高级语法时,如 async/await 时,则需要借助 代码转换工具 来支持这些语法。

  • 无法支持一些无法被 Polyfill 的 API,比如Proxy 对象

注:由于实现原因与 iOS JavaScriptCore 限制,iOS 环境下的 Promise 是一个使用 setTimeout 模拟的 Polyfill。这意味着 Promise 触发的任务为普通任务,而非微任务,进而导致 在 iOS 下的 Promise 时序会和标准存在差异

3.2.2 小程序的运行机制

【uni-app&微信小程序&React Native】跨端原理初探

  • 冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。

如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。 从小程序生命周期的角度来看,我们一般讲的「启动」专指冷启动,热启动一般被称为后台切前台。

  • 小程序启动后,界面被展示给用户,此时小程序处于「前台」状态。
  • 当用户「关闭」小程序时,小程序并没有真正被关闭,而是进入了「后台」状态,此时小程序还可以短暂运行一小段时间,但部分 API 的使用会受到限制。

切后台的方式包括但不限于以下几种:

  • 点击右上角胶囊按钮离开小程序
  • iOS 从屏幕左侧右滑离开小程序
  • 安卓点击返回键离开小程序
  • 小程序前台运行时直接把微信切后台(手势或 Home 键)
  • 小程序前台运行时直接锁屏
  • 小程序进入「后台」状态一段时间后(目前是 5 秒),微信会停止小程序 JS 线程的执行,小程序进入「挂起」状态。此时小程序的内存状态会被保留,但开发者代码执行会停止,事件和接口回调会在小程序再次进入「前台」时触发。

当开发者使用了后台音乐播放后台地理位置等能力时,小程序可以在「后台」持续运行,不会进入到「挂起」状态

  • 小程序销毁:如果用户很久没有使用小程序,或者系统资源紧张,小程序会被「销毁」,即完全终止运行。

具体而言包括以下几种情形:

  • 当小程序进入后台并被「挂起」后,如果很长时间(目前是 30 分钟)都未再次进入前台,小程序会被销毁。
  • 当小程序占用系统资源过高,可能会被系统销毁或被微信客户端主动回收。

4. React Native原理

从 0.68 版本开始,React Native 提供了新架构,它为开发者提供了构建高性能和响应式应用的新功能。

4.1 旧架构

下面架构图来自Deep dive into React Native’s New Architecture

【uni-app&微信小程序&React Native】跨端原理初探

4.1.1 三线程

React Native主要有3个线程:

  • JavaScript Thread:Metro(打包工具)将React源码打包成JS Bundle文件,然后传入JavaScriptCore引擎进行执行
  • Native/UI Thread:负责原生UI渲染Native UI和调用原生API能力Navite Module(比如蓝牙、照相机等)
  • Shadow Thread:创建Shadow Tree模拟React结构树,用于在将元素渲染到主机屏幕之前计算元素的布局

4.1.2 Bridge

JS ThreadUI Thread之间的通信称为Bridge,通过Bridge发送数据时,有几个特点:

  • 批处理:对Native调用进行排队,批量处理
  • 序列化:通过JSON格式来传递消息,每次都要经历序列化和反序列化
  • 异步:消息队列是异步的

即通过Bridge发送数据时,必须对其进行批处理(优化)并序列化为 JSON

4.1.3 JavaScriptCore

JavaScriptCore是一个JS引擎,IOS系统自带了该引擎。为了统一Android和IOS使用同一个JavaScriptCore,React Native会将JavaScriptCore和app打包在一起,

  • 从 React Native 0.70 版本开始,React Native 会默认使用Hermes引擎,它是专门为 React Native 而优化的一个新式开源 JavaScript 引擎。
  • 如果 Hermes 被禁用或是较早的 React Native 版本,则会使用JavaScriptCore,也就是 Safari 所使用的 JavaScript 引擎。但是在 iOS 上 JavaScriptCore 并没有使用即时编译技术(JIT),因为在 iOS 中应用无权拥有可写可执行的内存页(因此无法动态生成代码)。
  • 在使用 Chrome 调试时,所有的 JavaScript 代码都运行在 Chrome 中,并且通过 WebSocket 与原生代码通信。此时的运行环境是V8 引擎。(社区也有提供可以在生产环境中使用的react-native-v8)

从 0.68 版本开始,React Native 提供了新架构,它为开发者提供了构建高性能和响应式应用的新功能。因此从 0.70 版本开始,会使用Hermes引擎

4.1.4 Yoga

它是布局引擎的名称,用于计算用户屏幕的 UI 元素的位置

4.1.5 渲染流程浅析

  1. 布局使用React编写,转化为Virtual DOM Tree后,JavaScript Thread使用Bridge发送序列化的JSON数据给Native/UI Thread,告诉它如何创建或者更新原生UI
  2. 这个时候Native/UI Thread会将数据发送给Shadow ThreadShadow Thread通过维护一个 Shadow TreeShadow Tree 可以理解为是 Virtual DOM TreeNative 的映射,拥有和 Virtual DOM Tree 相同的树形层级关系)来计算 Virtual DOM TreeNative 页面的实际布局
  3. 计算完成后Shadow Thread返回数据异步通知Native/UI Thread进行创建或者更新原生UI

React Native不适合绘制特别复杂的界面以及复杂的动画,效果比不上原生的效果

4.2 新的架构

从 0.68 版本开始,React Native 提供了新架构,它为开发者提供了构建高性能和响应式应用的新功能。

下面架构图来自Deep dive into React Native’s New Architecture

【uni-app&微信小程序&React Native】跨端原理初探

4.2.1 旧架构的问题

旧的架构曾经通过使用一个叫做桥(Bridge)的组件将所有必须从 JS 层传递到本地层的数据序列化来工作。桥可以被想象成一条总线,生产者层为消费者层发送一些数据。消费者可以读取数据,将其反序列化并执行所需的操作。桥有一些固有的限制:

  • 它是异步的:某个层将数据提交给桥,再异步地"等待"另一个层来处理它们,即使有时候这并不是真正必要的。
  • 它是单线程的:JS 是单线程的,因此发生在 JS 中的计算也必须在单线程上进行。
  • 它带来了额外的开销:每当一个层必须使用另一个层时,它就必须序列化一些数据。另一层则必须对其进行反序列化。这里选择的格式是 JSON,因为它的简单性和人的可读性,但尽管是轻量级的,它也是有开销的。

4.4.2 新架构的改进

新架构放弃了"桥"的概念,转而采用另一种通信机制:JavaScript 接口(JSI)。JSI 是一个接口,允许 JavaScript 对象持有对 C++ 的引用,反之亦然。

一旦一个对象拥有另一个对象的引用,它就可以直接调用该对象的方法。例如一个 C++ 对象现在可以直接调用一个 JavaScript 对象在 JavaScript 环境中执行一个方法,反之亦然。

这个想法可以带来几个好处:

  • 同步执行:现在可以同步执行那些本来就不应该是异步的函数。
  • 并发:可以在 JavaScript 中调用在不同线程上执行的函数。
  • 更低的开销:新架构不需要再对数据进行序列化/反序列化,因此可以避免序列化的开销。
  • 代码共享:通过引入 C++,现在有可能抽象出所有与平台无关的代码,并在平台之间轻松共享它。
  • 类型安全:为了确保 JS 可以正确调用 C++ 对象的方法,反之亦然,因此增加了一层自动生成的代码。这些代码必须通过 Flow 或 TypeScript 类型化的 JS 规范来生成。

参考文章

  1. 跨端框架一些原理分析
  2. React-Native — 原理探究
  3. 微信小程序官方文档
  4. uni-app官方文档
  5. React Native架构对比
  6. React Native 技术详解 (一) - 认识它
  7. Deep dive into React Native’s New Architecture