GMTC北京站9折购票最后一周,2022年大前端方向又有哪些技术热点? 了解详情
写点什么

React Native 优先的多端统一化方案

  • 2020 年 12 月 27 日
  • 本文字数:3096 字

    阅读完需:约 10 分钟

React Native 优先的多端统一化方案

一、方案背景


长期以来 APP、H5、小程序等各个端的定位和发展历程都不一样,各端技术栈差异性也较大,基于成本和效率考虑并不追求各端一致性,结果就是各端真的就渐行渐远了。


移动端增量红利越来越少的情况下,产品这边逐渐追求各端的产品体验一致性,多端同时上的需求越来越多,但是由于技术上割裂较大,工时基本都会按端加倍,开发成本奇高,迫切的需要一套减少多端开发成本的方案。


二、方案调研


开始之前我们对业界现有的一些跨端方案进行了简单的调研和了解。



通过对比目前的多端开发主要有以下几个大方向:


  1. 对 IOS 和 ADR 的 native 端 APP 的适配

  2. 中国特色的针对各小程序平台的适配

  3. 都希望可以兼顾到对 H5 的转换


而实现方向上看起来五花八门,但总体思路上主要还是两个大方向:


  1. 提供自定义 DSL 静态编译转化成目标源代码(运行体验好)

  2. 运行时适配兼容(开发体验好)


这两种方式的优缺点都非常明显(相关框架和方案对比文章都较多,可自行详细了解)。目前社区基本都想在运行上努力,开发当然要自己爽啊,实际体验下来除了在微信小程序上性能问题较大之外,也没啥大毛病。


taro 作为较早的多端方案,适配性和兼容性都不错,自定义 DSL,JSX 由于其转译复杂性限制也较多。


taro-next 和 remax 都是运行时适配的方案,而 remax 的口号是 “使用真正的 react 构建小程序” (好好体会,后面要考)。


Chameleon 是号称兼容性和运行效率上都比较高的,编译和运行时适配的技术都用到了,不过由于他是支持的 weex 就没做深入尝试了。


其他像 alita,KBone,react-native-web 都在自己的小领域内能较好的运行。


三、方案介绍


1、解决思路


调研完发现上面的方案其实并不能很好的直接解决我们的问题:


Qunar 整体技术栈以 react 为主,几年前已将 APP 整体迁移到 RN 技术栈上,解决了 IOS 和 ADR 的 2 端问题。APP 的体验和开发是最重要的,不能为了多端用新的 DSL 语法来限制对 RN 技术的使用,降低 RN 的性能和开发体验。基于现状,其实我们想要的是:能直接将 RN 转换到 H5 和各小程序平台的多端方案,可惜没有。


不能直接找到一次将 RN 运行到多端的方案,其实如果能分别解决 RN 到 H5 和 RN 到小程序的问题也是能达到目标的,分析前面的跨端方案还是有一定可行性的。



2、RN 到 H5


react-native-web 是 Twitter 开源的可将 RN 代码运行在 H5 上的方案,而且他们 H5 端的官网就是直接用 RN 转出来的,自信到连自己主站都敢用的方案肯定是要尝试一下的,于是出去看了下线上效果:



发现保真度和体验还可以,对该方案的实现原理进行了解之后,觉得 H5 可行,后续到小程序的方案也深受启发。


3、react-native-web 原理


先看一行 RN 代码:



再看 react-native-web 的源代码:



使用方式:



他的方案其实挺简单粗暴的,把 RN 的组件和 API 都用 H5 实现适配一遍,适配其行为和默认样式,在打包的时候使用 webpack 的别名机制将用到的组件替换成 react-native-web 里的对应组件。


简单的方案实现起来工作量还是挺大的,所以 react-native-web 里也大量的直接使用了 react-native 的源代码,谁让他们都是 JS 呢。


既然到 H5 可以这么简单粗暴,那到小程序是否可以呢?


4、RN 到小程序


我们知道小程序都有一套自己的 DSL 语言,而且与常规前端不同的是他将逻辑层和视图层完全隔离在了两个线程里,两边数据和对象都不共享,只能通过 Native 层来传递数据通讯。


RN 广义上来说也是一样的双线程机制,不过 RN 的渲染是用的 native,小程序用的是 webkit。


RN 是完全基于 React 语言的,比小程序的 DSL 要灵活复杂得多,要把 React 语法和 JSX 编译成一个子集的话困难性还是很大的。


这个时候我们想到了 remax:使用真正的 react 构建小程序。


如果我们像 react-native-web 一样,把 react-native 组件用 remax 来实现一遍,是不是就可以将 RN 运行到小程序上了呢?


5、remax 实现原理


这部分网上有详细的原理介绍,这里只简单说一下:


react 在内部做完 VirtualDOM 的更新后最终都要调用宿主环境的更新方法(add remove)来更新界面,为了更好地对接各个平台 react 提供了 react-reconciler 库来传入真正宿主元素的更新方法(HostConfig)。基于这个库可以方便的实现出 ReactDOM、RN 等 react 渲染层。remax 就是基于该组件实现的一个 react 的渲染层,不过小程序里不能直接去更新界面,所以 reamx 会把更新收集起来,然后生成一个更新数据通过小程序的 setData 触发渲染层的更新。然后在小程序渲染层实现一个通用模板来渲染这些数据。


这个方案带来的好处和缺点,在微信小程序里的性能限制下面 remax 和 taro next 的原理介绍里都讲得很透彻,这里就不在复述了。


remax 原理介绍:


https://juejin.im/post/6844904131157557262


taro next 也采用了类似的原理:


https://juejin.im/post/6844904036743774216


6、RN 到小程序组件库


基本原理同 react-natvie-web,只不过在对 RN 组件的具体实现上采用直接使用对接到 remax 组件上的方式。看代码例子的话目录结构等是不是都和 react-native-web 很像。



四、最终多端方案


最终经过调研和尝试,我们选择了按平台用不同的方案进行转换的方案:


  1. H5 上直接用 react-native-web 进行转换

  2. 到小程序端使用 reamx 组件实现一套 RN 的组件库,借用 remax 来适配到多端

  3. 借助 webpack 的特性来实现针对不同平台的打包




qrn-mirror 就是前面提到的针对 RN 组件到小程序的组件适配库,使用 remax 实现。


我们的主要工作量集中在 qrn-mirror 层对 RN 组件的适配,借助现有开源方案小成本的实现了这个事情。


当然在实现小程序组件的时候我们才理解 remax 只说了 “使用真正的 react 构建小程序” , 从来没说过支持多端一致的,这差别你体会体会……不过幸运的是 remax 确实也通过 remax/one 提供了多个多端兼容的基础组件。当然我们最终还是选择继续使用 remax 来开发了组件库,谁让他是完整支持 react 的呢,另一个我们也不追求一次把所有小程序端都适配了。


五、多端动态方案


前面实现了将 RN 代码在多端运行的机制,但是在实际迁移中并不是所有的 RN 特性小程序和 H5 都能支持,产品和交互本身也有差异,这时候还是需要对各端做差异化和降级的。


如何做到多态其实 webpack 都已经替我们做好了,我们只需要用和定好规范就好了。


1、文件内小范围的多态


借助 webpack 的 tree shaking 和 webpack.DefinePlugin 插件,可实现按端执行逻辑且不出现冗余代码。



2、文件组件级别的多态


受益于 react 良好的组件化机制,只要我们按文件导出同样 API 的 react 组件,可以无缝的针对多端做替换。remax 也能做到自动识别小程序的原生组件。而我们只需要根据平台动态修改 webpack 查找文件后缀的优先级顺序就好了。



最终打包时在 H5 端使用 index.web.js 内导出的兼容组件,其他端用 index.js 里导出的组件。


六、效果展示


最终我们实现了一个开发工具,在规范 RN 工程目录结构的情况下可以一键转换出 H5 和小程序的版本。目前已经在低价机票,机票订单详情,公共订单列表等项目中进行了应用。后续也希望在主流程和更多新项目中直接使用。



七、后续计划


这次我们只分享了整个方案的大致思路,后续会逐步分享一些我们在实践过程中踩的一些坑和应对方案。


  1. 第三方不侵入打包过程介绍

  2. 和 nanachi 的环境整合方案

  3. react,react-native-web, remax 的版本对应和锁定问题

  4. 小程序不支持全局 global 对象的问题

  5. 小程序中 RN 动画解决方案

  6. 小程序中的渲染性能优化

  7. stylesheet 样式解决方案

  8. 多平台工程的工程结构限制

  9. 库 Size 大小分析优化过程和解决方案



头图:Unsplash

作者:冯地木

原文React Native 优先的多端统一化方案

来源:Qunar 技术沙龙 - 微信公众号 [ID:QunarTL]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2020 年 12 月 27 日 22:371845

评论

发布
暂无评论
发现更多内容

软件工程师的专业素养解读(二)

卢卡多多

职业素养 软件IT专业 11月日更

架构实战营 -毕业总结

思梦乐

云知声 Atlas 超算平台: 基于 Fluid + Alluxio 的计算加速实践

阿里巴巴云原生

阿里云 云原生 实践 Fluid Alluxio

开源项目——swift开发记事本APP

思想者杰克

开源项目——FLutter/iOS/Android编写的三个计算器APP

思想者杰克

你管这破玩意叫锁

中间件兴趣圈

高并发 java; 11月日更

复习

IT蜗壳-Tango

11月日更

杂谈——什么是Google Fuchsia ?

思想者杰克

HashMap 中的一个“坑”!

王磊

Java hashmap LinkedHashMap

Redis利用漏洞

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

架构实战营 - 模块七作业

Alex.Wu

王者荣耀商城异地多活架构设计

guangbao

tar 备份linux系统

入门小站

Linux

开源项目——5种技术编写的7个demo工程

思想者杰克

04 K8S之生态系统

穿过生命散发芬芳

k8s 11月日更

端开发技术——解密Flutter响应式布局.md

思想者杰克

0 基础架构入门 - 7(王者荣耀商城异地多活架构设计)

felix

架构实战营 0 基础架构入门

模块七:王者荣耀商城异地多活架构设计(作业)

紫云

小谈音视频质量检测

声网

人工智能 音视频

linux系列之: 你知道查看文件空间的两种方法吗?

程序那些事

Linux 操作系统 程序那些事 11月日更

开源项目——FLutter开发录音APP

思想者杰克

模块7作业

4anonymous

极客时间架构实战营模块7作业

jjn0703

架构实战营

王者荣耀商城异地多活架构设计 - 模块 7

刘琦Logan

架构实现训练营|第7课|作业

Frode

架构实战营

算法,从今天开始

ES_her0

11月日更

干货!Spring Cloud微服务架构进阶,你还不了解的都在这里

Java 程序员 架构 微服务 SpringCloud

架构训练营毕业总结

小卷儿

算法—算法的时间空间复杂度

思想者杰克

端开发技术——FLutter开发即时通讯

思想者杰克

学生管理系统架构设计文档

deng

架构实战营

WAVE SUMMIT 2022 深度学习开发者峰会

WAVE SUMMIT 2022 深度学习开发者峰会

React Native 优先的多端统一化方案_语言 & 开发_Qunar技术沙龙_InfoQ精选文章