跨端技术 | 青训营笔记

120 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

学习了跨端的相关技术

课堂笔记(一)

跨端背景

业务场景增加;PC端,移动端,web端,IoT设备

痛点:

  1. 功能基本一致
  2. 开发维护成本
  3. 安卓,iOS发版周期长

目标:

  1. 研发效率高。学习成本,开发一致性
  2. 用户体验好。稳定性,性能
  3. 动态化。动态化下发,满足业务需求

跨端技术

hybrid(混合)方案

基于webView渲染,通过JS Bridge把一部分系统能力开放给JS调用

image-20230203160256876

WebView容器的工作原理是基于Web技术来实现界面和功能,通过将原生的接口封装、暴露给JavaScript调用,JavaScript编写的页面可以运行在系统自带的WebView中。这样做的优势是,对于前端开发者比较友好,可以很快地实现页面跨端,同时保留调用原生的能力,通过搭建桥接层和原生能力打通。但这种设计,跨端的能力受限于桥接层,当调用之前没有的原生能力时,就需要增加桥。另外,浏览器内核的渲染独立于系统组件,无法保证原生体验,渲染的效果会差不少。

原生渲染方案

通过JS方案,通过中间层桥接后使用原生组件来渲染UI界面

React Native

image-20230203160358630

image-20230203160440193

React Native 的思路是最大化地复用前端的生态和 Native 的生态,和 WebView 容器的最大区别在于 View 的渲染体系。React Native 抛弃了低效的浏览器内核渲染,转而使用自己的 DSL 生成中间格式,然后映射到对应的平台,渲染成平台的组件。相对 WebView 容器,体验会有一定的提升。不过,渲染时需要 JavaScript 和原生之间通信,在有些场景可能会导致卡顿。另外就是,渲染还是在Native层,要求开发人员对Native有一定的熟悉度。

React Native 是一主要有JSI、Fabric、TurboModules 组成。

JSI是Javascript Interface的缩写,一个用C++写成的轻量级框架,它作用就是通过JSI,JS对象可以直接获得C++对象(Host Objects)引用,并调用对应方法。有了JSI,JS和Native就可以直接通信了,调用过程如下:JS->JSI->C++->ObjectC/Java。JSI是整个架构的核心和基石,所有的一切都是建立在它上面。JSI 将支持其他 JS 引擎;JSI 允许线程之间的同步相互执行,不需要 JSON 序列号等耗费性能的操作;JSI 是用 C++ 编写,以后如果针对电视、手表等其他系统,也可以很方便地移植;自此三个线程通信再也不需要通过Bridge,可以直接知道对方的存在,让同步通信成为现实。具体的用法可以看 官方例子。另外一个好处就是有了JSI,JS引擎不再局限于JSC,可以自由的替换为V8,Hermes,进一步提高JS解析执行的速度。

FabricFabric 是新的渲染系统,它将取代当前的 UI Manager。UI Manager:当 App 运行时,React 会执行你的代码并在 JS 中创建一个 ReactElementTree ,基于这棵树渲染器会在 C++ 中创建一个 ReactShadowTree。UI Manager 会使用 Shadow Tree 来计算 UI 元素的位置,而一旦 Layout 完成,Shadow Tree 就会被转换为由 Native Elements 组成的 HostViewTree(例如:RN 里的 会变成 Android 中的 ViewGroup 和 iOS 中的 UIView)。而之前线程之间的通信都发生在 Bridge 上,这就意味着需要在传输和数据复制上耗费时间。通过JSON格式来传递消息,每次都要经历序列化和反序列化。而得益于前面的 JSI, JS 可以直接调用 Native 方法,其实就包括了 UI 方法,所以 JS 和 UI 线程可以同步执行从而提高列表、跳转、手势处理等的性能。

Turbo Modules在之前的架构中 JS 使用的所有 Native Modules(例如蓝牙、地理位置、文件存储等)都必须在应用程序打开之前进行初始化,这意味着即使用户不需要某些模块,但是它仍然必须在启动时进行初始化。Turbo Modules 基本上是对这些旧的 Native 模块的增强,正如在前面介绍的那样,现在 JS 将能够持有这些模块的引用,所以 JS 代码可以仅在需要时才加载对应模块,这样可以将显着缩短 RN 应用的启动时间。