写在前面

Airbnb 早在 2016 年就上了 React Native 大船,是很具代表性的先驱布道者:

却在 2018 年初宣布Sunsetting React Native

从全面拥抱 React Native 到回归 Native,在这期间发生了什么?

押宝 React Native

人力吃紧,只能另寻他途:

而新的选择就是 React Native:

Facebook 创造 React Native 的初衷一样,Airbnb 也希望能够借助 React Native 技术 move faster,不必为一个产品功能分平台开发两套移动端代码。但作为底线,希望引进的这项新技术也能达到 Native 既定的质量标准

事实上,React Native 也确实达到了 Airbnb 最初的预期:

并非有利而无害,在深度应用中发现了两个难题:

  • 与 Native 复杂特性的集成:如共享元素过渡动画、视差效果、地理围栏等
  • 与 Native 现有基建的配合:如网络、实验测试、国际化等

快乐并痛着

从 Airbnb 的实践经验来看,React Native 的优势在于:

  • 跨平台:进而实现三端设计语言的统一,以及 Web 与 Native 的代码高度复用
  • 切合 JS 生态:无缝接入 Redux、ESLint、Prettier、reselect、jest 等 JS 生态
  • 开发效率:无需等待编译,Flexbox 布局也更容易掌握
  • Native 扩展:任何 Native 能力都可以桥接到 React Native 中,同时,Native 现有的基础设施也能集成进来
  • 性能可接受:动画同 Native 一样流畅,体验上能够满足大多数场景,很少需要关注性能

跨平台特性带来的代码复用与三端统一的可能性是无可替代的优势,而支持 JavaScript 运行时使其得以进入 JS 生态,从而获得 Hot Reloading 等免编译体验,实现开发效率的提升

实际上,对于广泛关注的性能问题,并没有想象中的那么慢

在一些触碰到能力边界的场景下,都能通过 Native Bridge 来打破限制:

看起来很完美。但在另一些方面,React Native 确实也带来了不少痛楚,比如:

  • 自身成熟度不够:不如 Android、iOS 成熟,存在不确定的能力边界风险
  • JS 语言的不足:弱类型让重构变得很困难且极易出错(早期尚未提供TypeScript 支持
  • 类库建设门槛高:编写 React Native 类库需要熟知 3 个平台,否则容易出现平台特定的问题,对开发者要求很高
  • 部分特性支持度不佳:比如笨重的Native Bridge API,早期提供的无障碍访问 API 不健全,长 List 支持不如 Native 方案成熟、灵活,手势支持、JS 运行时环境存在平台差异……甚至长期以来不支持 Android 64 位(直到 2019 年 3 月的0.59 版本才支持 Android 64 位
  • 首屏性能硬伤:秒级的运行时初始化开销,以及几百毫秒的前置首屏渲染时间,根本无法满足闪屏等场景的性能要求
  • 额外负担:引入 React Native 意味着会让包体积增大 8~12MB,同时,由于其生态尚不成熟,开发中通常面临基建与特性迭代并行

技术自身的成熟度不够,加上(类库建设的高门槛导致的)开源生态发展缓慢,致使实际使用中为了应对需要快速打补丁的场景,通常要维护一份自己的 React Native,而这部分维护成本不容小视

另一方面,Native 多年沉淀的基础设施(崩溃监控等)都需要在 React Native 下重新建设(要么重写,要么桥接)一套,否则开发体验与效率是跟不上的:

首屏性能主要难点在于:

  • 初始化时间:初始化 React Native 运行时的开销在所难免,大型应用在即使在(2018 年的)高端设备上也需要几秒
  • 开始渲染的前置时间:先要经过 JS 线程、yoga 布局线程,取到足够的信息后才能在主线程开始渲染,这期间存在 280~440ms 的白屏时间

P.S.线程模型的限制还带来了另一些问题,比如:

团队组织如何跨平台?

技术也对组织架构造成了影响,这些挑战可能比技术问题更难解决

对工程师的要求

  • 平衡三端体验:React Native 本质仍然是 Native,因此 Native 基础设施不可或缺,而平台差异依旧存在,这让平衡三端体验变得相当困难
  • 跨团队定位问题:React Native 本身还在快速发展变化中,基建与特性迭代并行,加上大家都没有太多经验,让问题定位变得异常困难,甚至搞不清楚问题应该归属于哪个团队,还是来自上游的 React Native
  • 应对跨平台的复杂度:工程师大多熟悉一两个平台,而构建或调试时可能会涉及其它平台。更糟糕的是,面临这种跨平台的复杂度,工程师可能完全不知道问题该从何查起
  • 准备三套开发环境:React Native 工程师需要具备 3 套最新的开发环境,而每套环境都不那么容易搭建、学习和保持更新,每过几周都要花几个小时去更新这些环境

React Native 并不能完全屏蔽平台差异,那么就要求工程师了解这些差异,并谨慎地平衡三端体验。而跨平台带来的复杂度直接体现在问题排查链路上,工程师可能需要跨团队、跨技术栈地定位问题

团队组织面临的挑战

团队可能面临成员体感上的一些问题,例如:

  • 态度两极分化:实践经验表明,工程师对这项技术的接受程度上存在两极分化,有视之为三端统一银弹全力支持的,也有全然拒绝一点都不愿意用的
  • 感知上的迭代速度变慢:从工程师的角度来看,如果与 Native 相比,用 React Native 开发某个特性需要 1.5 倍的时间,他仍会认为花费时间更长了,尽管事实上(多平台)总共花费的时间减少了

在混合技术栈下,团队还需要考虑一些新的问题:

  • 团队如何划分、如何协作?
  • 如何高效地跨技术栈调试?
  • 如何跨平台测试、保证代码在多平台都能正常工作?
  • 如何决定新特性该用什么技术去实现?
  • 如何招聘和分配团队资源?

事实上,这种混合的技术栈也确实对人员招聘、团队划分、技术实现、培训教学等造成了一系列影响:

  • 人员招聘:业界对企业贴上了 React Native 标签,很多工程师为此犹豫是否加入,影响人员招聘
  • 团队划分:混合的团队经常面临技术和沟通上的问题,因为代码被拆成了两份,工程师不再熟知整个逻辑流程,共享业务逻辑、模型、状态等变得很困难。虽然这些问题可以通过共享资源和代码来解决,但多数团队尚未形成这样的良好氛围
  • 平衡多技术栈:哪些代码应该由 Native 实现,哪些应该放在 React Native 里,是需要权衡的。而工程师通常不考虑这些,偏向于用选用自己熟悉的技术栈,导致一些代码不那么理想
  • 培训教学:比起 Native 10 多年的资源积淀,React Native 相关的学习资源和文档还是太少,意味着还需要在技术及内部基础设施的教学培训上投入一些资源

放弃 React Native,回归 Native

经过 2 年的实践验证,确认 React Native 并不能完全满足最初的预期

  • Move Faster:顺利时,开发速度确实无与伦比,但各种技术上和组织上的问题大大拖慢了这种速度
  • 达到 Native 既定的质量标准:React Native 的不断成熟与实践中积累的经验带来了一些性能提升,但有些技术问题(比如初始化和首屏异步渲染)仍然充满挑战,内部外部的资源匮乏加剧了这种困难
  • 不必为一个产品功能分平台开发两套移动端代码:React Native 代码几乎都能跨平台复用,但在 Airbnb App 里这部分代码占比很小,而且需要桥接大量的基础设施,所以实际结果是要在 Android、iOS、React Native 三个平台开发,而不止 Native 双平台
  • 提升开发体验:开发体验一言难尽,编译时间上表现很好,调试体验却很糟

由于以上种种,深思熟虑之后,Airbnb 最后决定全面放弃 React Native

具体的,自 2018 年 6 月起,所有特性迭代不再考虑 React Native 技术,相关开源项目也不再维护,并计划将高流量业务在 2018 年底全部迁由 Native 实现,逐步去除 React Native 带来的性能负担(比如启动时的初始化时间)

React Native 启发之下的 Native 开发

虽然放弃了继续使用 React Native,但在这 2 年中,Airbnb 也受到了一些对 Native 很有价值的启发

例如:

  • Server-Driven Rendering:动态更新
  • Epoxy Components:声明式组件定义、懒加载、基于虚拟 DOM 的更新机制
  • MvRx:线程模型
  • 编译速度提升:模块化编译

Server-Driven Rendering

服务驱动的 Native 渲染(Server-Driven Rendering):

用于动态更新等场景:

Epoxy Component

Epoxy是一套声明式的 Native 组件化方案,支持 Android 和 iOS:

其中,借鉴了 React 基于虚拟 DOM 的组件更新思路:

MvRx

融合通用开发模式及一些 React 思想形成的 Android 开发框架,MvRx

编译速度

通过拆分模块来缩减编译时间:

为什么这么难?

至此,React Native 在 Airbnb 的故事结束了

从押宝 React Native,到遭遇技术、团队组织难题,再到权衡利弊之后决定放弃,最后转而全力投入 Native 体系,并将 React Native 的一些思路应用进去……为什么这么难?连大型企业都无法驾驭这项新技术吗?

客观地讲,Airbnb 遭遇的许多困难都源自 Native 与 React Native 的混合应用(把 React Native 集成到现有的 Native App 中):

Facebook 直到2018 年 6 月计划解决通过大规模的重构来解决混合应用中存在的各种问题

而这些问题中的很多难点都是 Airbnb 所经历过,并且与之不懈斗争的。与一些小规模企业相比,Airbnb 有能力走得更深更远,所以也遭遇了更多更大的难题:

虽然早期信徒 Airbnb 选择了放弃,但 React Native 仍在继续高速发展,并日趋成熟:

因此,对于很多其他企业(PinterestInstagram等等)而言,React Native 仍然是不错甚至最好的选择

参考资料

有所得、有所惑,真好

关注「前端向后」微信公众号,你将收获一系列「用原创」的高质量技术文章,主题包括但不限于前端、Node.js以及服务端技术

本文首发于 ayqy.net,原文链接 http://www.ayqy.net/blog/reac...

03-05 20:21