写点什么

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:373201

评论

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

从持续交付到业务创新(上):互联网时代研发效能的核心

阿里云云效

云计算 阿里云 云原生 研发效能 持续交付

字节跳动流式数据集成基于Flink Checkpoint两阶段提交的实践和优化背景

字节跳动数据平台

大数据 flink 字节跳动 数据集成

科技筑基、高效实战:中科柏诚信云链正当时

联营汇聚

TSP 平台场景中的 MQTT 主题设计|车联网平台搭建从入门到精通 03

EMQ映云科技

开源 物联网 IoT mqtt emq

中国企业的测试之道被美国学习了?

博文视点Broadview

阿里通过度量把发版过程的不确定变成确定-构建闲鱼版本持续交付管道及度量

阿里云云效

云计算 阿里云 DevOps 云原生 度量

web前端培训React合成事件原理解析

@零度

React web前端开发

31岁的Python,蝉联年度编程语言排行榜冠军

JackTian

Python 编程 程序员 编程语言 后端

金三银四的 Vue 面试准备

CRMEB

资金管理系统解决方案

低代码小观

资产管理 企业管理系统 资金安全 CRM系统 客户关系管理系统

产品手册怎么做?用什么软件?

小炮

电路模型和电路定律 (Ⅱ)

謓泽

3月月更

阿里巴巴开源大规模稀疏模型训练/预测引擎DeepRec

阿里云大数据AI技术

机器学习 深度学习 搜索引擎 分布式训练 推荐引擎

打印总是遇到问题?一文教你如何在优麒麟上使用 CUPS 管理打印机

优麒麟

Linux 终端 优麒麟 打印机管理

JVM自定义类加载器在代码扩展性的实践

vivo互联网技术

JVM java 编程

Java培训基础高频面试题八股文分享

@零度

JAVA开发

龙蜥社区新增100+家合作伙伴,堡塔、东方通、宝德等头部企业均已加入

OpenAnolis小助手

开源 适配 合作伙伴 龙蜥社区 龙头企业

大数据培训flink8 个高频面试实战题分享

@零度

大数据 flink

6张图为你分析Kafka Producer 消息缓存模型

华为云开发者联盟

kafka 消息 Kafka Producer 消息缓存模型 消息缓存

动态卡片:富媒体内容井喷式增长下,新一代移动端动态研发的模式

蚂蚁集团移动开发平台 mPaaS

ios android 前端 mPaaS 卡片技术

python下载酷狗音乐上的歌曲,作为一个Python程序员你还不会JetPack

程序媛可鸥

Python 程序员 面试

技术平台&应用开发专题月 | 赋能企业业务快速创新,实现云原生自由

用友BIP

用友 用友iuap

JSON Schema 实现复杂结构表单数据展示

全象云低代码

前端 低代码 表单 JSON Schema

云小课|如何实现数据跨链交互?

华为云开发者联盟

区块链 数据 跨链 数据跨链 可信跨链服务

带你了解2022两会黑科技:阿里云视频云「AI编辑部3.0」

阿里云视频云

云计算 阿里云 AI 音视频 视频云

隐私安全的必答题,网易云信如何解?

网易云信

隐私安全

Python——Scipy库,熬夜整理华为最新Python笔试题

程序媛可鸥

Python 程序员 面试

ShardingSphere-Proxy 5.0 分库分表(一)

神农写代码

从持续交付到业务创新(下):有效的业务创新

阿里云云效

云计算 阿里云 云原生 研发效能

ModStartCMS模块化建站系统 v3.5.0 多图字段支持,系统优化升级

ModStart开源

如何实现24小时客户服务

小炮

客户服务

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