ReactNative进阶(五十九):存量 react-native 项目适配 HarmonyOS NEXT
文章目录
- 一、前言
- 二、ohos_react_native
- 2.1 Fabric
- 2.2 TurboModule
- 2.2.1 ArkTSTurboModule
- 2.2.2 cxxTurboModule:
- 三、拓展阅读
一、前言
2024年10月22日19:00,华为在深圳举办“原生鸿蒙之夜暨华为全场景新品发布会”,主题为“星河璀璨,共见鸿蒙”。本次活动上,华为正式发布“纯血鸿蒙”系统HarmonyOS 5.0
(即HarmonyOS NEXT
),据华为常务董事、终端BG董事长余承东透露,该系统是鸿蒙诞生以来的最大一次升级。
值得注意的是,HarmonyOS 5.0
是我国首个国产移动操作系统,也是继苹果iOS和安卓系统后,全球第三大移动操作系统。
为保证存量APP功能在鸿蒙NEXT系统可以正常使用,需保证基于RN框架开发的存量APP功能适配鸿蒙NEXT。
二、ohos_react_native
跨平台开发框架层面,除了 Flutter
支持鸿蒙外,React Native
社区支持的 ohos_react_native
也终于在 OpenHarmony-SIG 对外开源,并且和 Flutter
不同在于,本次开源的版本是基于 React Native 0.72.5
。
ohos_react_native
基于 0.72.5
,也就是距离 0.76 New Architecture Default
虽然还有几个版本之差,但是它确确实实支持 New Architecture
里的大部分能力,例如 “Interop Layers”
(毕竟官服强制新架构,迁移第三方算支持 IL
),和最新版本相比,也就是不支持 Bridgeless Mode
和 Suspense & Transitions
而已。
这也是和 Flutter
鸿蒙版的最大不同之处,基于 React Native 0.72.5
的 ohos_react_native
可以使用 New Architecture
里的大部分支持,而 Flutter
目前还未兼容至 Impeller
。
可以看到,ohos_react_native
在 React Native
新架构基础上进行了鸿蒙化适配,也就是类似 JSI
、Fabric
、TurboModule
、CodeGen
和 Hermes Engine
的能力,在 OpenHarmony
版本都得到了保留支持,并且通过原生平台的 API 进行了适配。
例如,在 OpenHarmony
适配层会接收 React Common
传过来的数据,对接原生的代码,调用 ArkUI
的原生组件与 API,核心主要是包括了两个部分: TurboModule
与 Fabric
。
2.1 Fabric
Fabric
是 React Native
新架构下的渲染系统,取代了原本的 UI Manager
, 接收 React Native
传过来的组件信息,处理后发送给原生 OS,由 OS 完成页面的渲染。
目前主流的移动端跨平台技术方案大体可以分为三类,
- 使用原生内置浏览器加载
HTML5
的Hybrid
技术方案,采用此种方案的主要有Cordova
、Ionic
和微信小程序;- 使用
JavaScript
语言进行开发,然后使用原生组件进行渲染,采用此方案的主要有React Native
、Weex
和轻快应用;- 使用自带的渲染引擎和自带的原生组件来实现跨平台,采用此种方案的主要是
Flutter
。
ohos_react_native
一开始是直接用 N-API
的,在经历早期将控件转化为 ArkUI
控件的效果“不尽如人意”之后,ohos_react_native
直接使用 XComponent
对接到 ArkUI
的后端接口进行渲染,从而缩短了流程,提高了组件渲染效率,也就是大家常说的 C-API
。
ohos_react_native
在文档中表示,C-API
的性能收益包括以下的几个部分:
- C 端最小化、无跨语言的组件创建和属性设置;
- 无跨语言前的数据格式转换,不需要将
string
,enum
等数据类型转换为object
,可以在 CPP 侧直接使用对应的数据进行处理; - 可以进行属性 Diff,避免重复设置,降低了属性设置的开销。
Taro 也曾在他们的文章中表示过,因此在
ArkTS
版本中,在CSS
的解析和属性应用阶段占用了过多的时间,在CAPI
版本进行了CSSOM
模块的架构升级后,带来了明显的性能提升。
这里的实现主要依赖 XComponent
完成,XComponent
在 ArkUI
上主要提供用于图形绘制和媒体数据写入的 Surface
,XComponent
负责将其嵌入到视图中,支持应用自定义 Surface
位置和大小,需要 API 10
,并且在 API 12
开始支持在元服务中使用。
也就是 XComponent
类似一个 Surface
的存在,一般情况下用于相机预览或者视频播放,需要支持 EGL/OpenGLES
等相关的应用场景。
从 ohos_react_native
提供的资料可以看到,类似直接越过 ArkUI
前端,利用后端 XComponent
的渲染能力实现很眼熟?其实就类似于 Flutter
上的实现。
不严谨的说,之前鸿蒙 RN 是把 React Component
映射成 Widget
,那么 C-API
版本的鸿蒙 RN 则是利用 JSI
把 React Component
直接在 C++
层映射成 RenderingObject
。
所以在基于ArkUI C-API
的适配方案中,rootView
是一个 XComponent
,用于占位,并挂载 C-API
的组件。
另外,在目前的 C-API
中组件中是支持渲染 ArkTS
组件,但是仅支持叶子节点如 Image
,不支持容器节点 如Stack
等,也就是 C-API
组件一般情况下是可以和 ArkTS
叶子组件混合开发。
总的来说,ohos_react_native
的后续路线都是 C-API
,并且三方库后续也只基于 RN C-API
架构演进,例如第三方库中所有的非叶子节点(容器型)库都需要进行了 C-API
化适配,如 react-native-safe-area-context
、react-native-linear-gradient
和 react-native-svg
等,这是适配鸿蒙时需要格外注意的。
目前
ohos_react_native
的 NPM 公仓坐标是@react-native-oh-tpl
,官服一共准备迁移 300 多个
package ,截止到目前已经迁移了 70 多个迁移的包。
2.2 TurboModule
TurboModule
是 React Native
中用于 JS 和原生代码进行交互的模块,而 Turbo Modules
里 JS 将能够持有这些模块的引用,所以 JS 代码可以仅在需要时才加载对应模块,这样可以将显着缩短 RN 应用的启动时间。
在目前 ohos_react_native
里,根据是否依赖 HarmonyOS系统相关的能力,可以分为 cxxTurboModule
和 ArkTSTurboModule
。
2.2.1 ArkTSTurboModule
ArkTSTurboModule
为 React Native
提供了调用 ArkTS
原生 API 的方法,可以分为同步与异步两种。
ArkTSTurboModule
依赖 NAPI
进行原生代码与 CPP 侧的通信,包括 JS 与 C 之间的类型转换,同步和异步调用的实现等。
2.2.2 cxxTurboModule:
cxxTurboModule
主要提供的是不需要系统参与的能力,例如 NativeAnimatedTurboModule
主要提供了数据计算的相关能力。
cxxTurboModule
不依赖于系统的原生 API,为了提高相互通信的效率,一般是在 cpp 侧实现,这样可以减少 native 与 cpp 之间的通信次数,提高性能。
从官方提供这部分内容看,目前 ohos_react_native
在 TurboModule
和 react native
还是存在一定差别,至少不会是类似 0.73
的完全 Bridgeless Mode
模式。
同样,TurboModule
支持使用 Codegen
生成原生代码 ,这里采用的是 react-native codegen-harmony
的相关脚本支持,同时在 CMakeLists.txt
中会添加新增的胶水代码文件,需要在 CMake
文件中把Codegen
生成的文件分别使用 add_library
和 target_include_directories
添加到编译构建的任务中,生成对应 so
。这里也可以看到 C-API
的"“影子”"。
三、拓展阅读
- ohos_react_native