InfoQ|耗时三年,向 React 迁移的利与弊

作者 | Bryan Clark 本文最初发布于 khanacademy.org 网站 , 经网站授权由 InfoQ 中文站翻译并分享 。
2017 年 , 可汗学院( https://blog.khanacademy.org)开始在 iOS 和 Android 应用中使用 React Native 。 到了今年 , 这一迁移工程终于来到了终点 , 可汗学院应用中的所有页面都转到了 React Native 上 。
2017 年 , 可汗学院之所以开始这一实验 , 主要是基于以下考虑:

  • iOS 和 Android 应用的设计几乎是一致的 , 交互设计、功能和内容都没什么区别 。
  • 维护两个代码库是很困难的事情 , 尤其是这两个代码库还具有不同的数据设计、错误和开发新功能时的考虑要素 。
  • 学院的移动开发团队很小 , 因此迁移工作不会涉及大批工程师 。
  • 学院的网站已经在使用 React 了 , 因此学院的开发团队具备相应的专业知识 , 以及帮助迁移的概念和工具 。
下面具体讲一下维护两个代码库所要面临的挑战 。
  • 不同的平台上会出现不同的错误 。 当然 , React Native 也会有这种情况 , 但是出现概率就小得多了 。
  • 开发新功能需要针对两个平台分别考虑设计、工程和测试工作 。 这意味着你至少需要两名工程师(iOS 和 Android) , 并且他们最好共同工作——对于像可汗学院这样小规模的团队来说这是很大的负担 。
  • 功能和设计一旦构建好后就很难调整 , 因为每次调整都需要在两个平台上各来一次 。
  • 平台之间的架构差异很大 。 可汗学院的 iOS 代码库比 Android 代码库大四岁 。 iOS 有 Swift、ReactiveCocoa、Cartography 和 CoreData 。 Android 则有自己的一组依赖项和数据流设计 。 这些差异累加起来 , 让平台之间的功能复用变得很复杂 , 对比两个平台的代码也不容易 , 于是团队相当于被平台分割成了两部分 。
开始迁移 整个迁移过程基本上分为三个阶段:探索、跨越和灭绝 。
在探索阶段(2017 年初) , 团队开始在原生代码和 Javascript 代码之间架起桥梁 , 并开始使用 React Native 构建一些页面 。 几乎所有的网络、数据、业务逻辑和所有“客户端后端”内容都是通过桥梁传递的 。 这一阶段的工作涉及很多样板 , 因此非常繁琐 。
跨越阶段(2017 年中至 2018 年中)自然是最困难的 。 学院团队正式决定转向 React Native , 但离终点还有很远的距离 。 这时候 , 团队需要考虑三件事:原生 iOS、原生 Android 和 React 原生代码 。 工程师要做出一项更改时需要考虑两个(或更多)范式 , 并且有很多东西要学习!
灭绝阶段(2018 年中至 2020 年中)从学院的“流主题树”项目开始 , 该项目历时数月 , 将内容数据库(学院的许多课程、视频、文章和练习内容)从大型原生数据库(例如 CoreData)完全迁移到了轻量级 、 用 Javascript 编写的缓存库 。 至此 , 学院的客户端内容数据库转入了 React Native , 于是不需要在构建的桥梁上传递那么多内容了 , 并且可以开始删除许多原生代码 。 到今年的 v7.0 版本 , 应用的最后一个原生页面也会升级到 React Native , 同时统一了手机和平板电脑的导航设计 。
原生和 React Native 的混合体 开发团队将 React Native 用于“页面内容” , 而将原生代码用于这些页面的导航用途 。 这是为了物尽其用 , 并让应用尽量提供原生级的体验 。
应用的绝大多数“业务逻辑”都存在于页面内容中(例如“首页”标签中卡片的内容 , 或“书签”标签中的下载规则) 。 相比之下 , 标签栏或导航栏的内容在很大程度上不依赖业务逻辑 。
但是 , 用 React Native 编写的导航栏和导航控制器和原生版本还是有一些差异 , 这些差异加起来还是很可观的 。 原生导航控制器提供了正确的滑动后退手势 , 以及用于推 / 弹出动画的正确动画 timing 。 原生导航栏可轻松处理带刘海的 iPhone 。 在原生 UIViewController 中包装的页面也更符合开发习惯 。 (有很多库试图模仿系统的标准导航栏 , 但它们都无法满足可汗学院团队的需求 。 )
这个迁移项目的一条原则是迁移后的应用依旧要有原生级的体验 , 当然小问题总是会有的 , 但以此为代价 , 团队在许多方面为应用带来了明显的改进 。
国际化和本地化 移动应用的翻译工作主要有两部分组成:内容文本和平台文本 。 前者来自学院的内容管理系统 , 包括互动练习中的问题、视频的内容和字幕或文章中的文字 。 (许多内容文本是前面提到的“流主题树”的一部分 。 )平台文本是在移动应用的代码库中定义的 , 如“注册”按钮中的文字、标签栏项目的标题或“设置”页面中显示的文字 。
可汗学院有一些优秀的自制基础架构来维护平台文本 。 在 JavaScript 中定义一个字符串 , 然后就可以使用开发团队编写的 , 将字符串复制到原生 iOS 和 Android 字符串的脚本 。 这个工具很好用 , 团队可以轻松地在原生和 React Native 上重用字符串 , 这在“跨越”迁移阶段有很大帮助 。
从 2015 年至 2019 年 , 可汗学院的应用仅支持六个语言版本 , 但现在已达到了 19 个!共享的 iOS 和 Android 实现帮助团队构建了流主题树 , 这意味着添加其他语言不会让应用的体积大幅增加 。 此外 , 团队能够在 React Native 中设计轻松处理非拉丁字符的组件 。 应用的语言版本数量不再有技术瓶颈 , 而只取决于学院有多少翻译库可用 。 这极大地鼓舞了学院的国际倡导者 , 让他们更好地为世界各地的用户宣传可汗学院 。
React Native 的体验 迁移到 React Native 并不是一帆风顺的 , 途中有很多坎坷 , 例如学习新语言、新的组件生命周期等 。 “跨越”时期尤其具有挑战性 。 原生代码和 React Native 代码之间的桥梁有很多烦人的样板代码 。
团队成员很想念 Swift 的关联值枚举、方便的初始化器、命名参数以及轻松向结构和类添加函数和变量的特性 。
但 React Native 也有很多好处 。
  • React Native 比 UIKit 更具延展性 。 调整和重构代码的体验很不错 。 例如 , 为 UICollectionView 编写的代码与 UITableView 和 UIStackView 是不一样的 , 但是在 React Native 中并不用操心这一点?在大多数情况下 , 你可以在重构时剪切并粘贴代码 , 将某些内容从网格更改为列表是非常简单的 。
  • 开发工具非常好用 。 方便的 VSCode 插件、linter 和自动修复器 , 大大减轻了开发人员和代码审核人员的负担 。
  • 就算开发人员并不怎么熟悉 Android 应用开发 , 也可以使用 React Native 编写 Android 应用 。
  • 熟悉 React Native 后 , 应用开发团队也有信心参与 Web 前端的开发工作了 。
现在的成果 可汗学院的 iOS 和 Android 应用现在共享一个代码库 , 开发团队可以专注于应用的功能开发 , 用不着关心平台的差异 。 这意味着随着时间的推移 , 应用的功能质量会越来越好 , 并且团队可以对功能进行渐进式改进了 。
  • 共享的基础架构使团队更容易迁移到 GraphQL , 从而简化了服务端向 Go 的迁移工作 。
  • 应用的体积明显缩小了 。 从大型内容库数据库切换到流式数据库 , 极大地减少了应用体积 。
  • 应用的开发团队与网站团队联系更紧密 , 两边的设计和功能也得以互通 , 整个组织的协作水平得到了提升 。
  • 应用中仍然有一些原生代码 , 必要时团队可以继续使用 Xcode 或 Android Studio 实现特定于平台的功能 , 例如 iPad 多任务处理 。
  • 团队创建了强大的设计系统 , 可帮助可汗学院的设计师和工程师快速协调产品的改进方案 。
下一步计划 可汗学院目前的主要工程项目是Goliath , 内容是将后端重新设计为一系列 Go 服务 。 统一的移动基础架构在这一迁移过程中起到了作用:虽然移动团队只有六名成员 , 也还是能继续构建新功能和修复程序 。 团队改善应用的功能、本地化、质量和性能的能力比以前强了很多 。
参考阅读:
InfoQ 写作平台欢迎所有热爱技术、热爱创作、热爱分享的内容创作者入驻!
还有更多超值活动等你来!
扫描下方二维码
填写申请 , 成为作者
开启你的创作之路吧~
InfoQ|耗时三年,向 React 迁移的利与弊
本文插图
【InfoQ|耗时三年,向 React 迁移的利与弊】点个在看少个 bug ??


    推荐阅读