Udacity 移动端团队最近删除了 App 中使用 React Native 语言开发的相关功能。css
咱们收到大量有关咱们用法或 React Native 的问题以及为何咱们中止投入资源和精力在 RN 上。java
在这篇文章中,我但愿可以回答咱们收到的大多数问题并深刻了解:ios
我固然不会声称本身是 React Native 的专家。咱们团队中的其余人比我有更有经验,但我相信他们也不会自称专家。git
我将根据咱们本身的经验谈论在咱们的特定状况下作什么和不作什么。至于 React Native 是否适合你的团队/项目取决于你,但但愿这篇文章可以提供额外有用的数据点供你参考。程序员
“React Native 是否适合你的团队/项目取决于你”web
我仍是想指出,这些经验和意见来自 Udacity 的移动工程团队,而不是其余任何人。这里的想法并不反映任何其余团队使用或构建 React 或 React Native 内容的意见。面试
首先要搞清楚的事情。咱们的团队是什么样的?团队规模,经验和所在组织有能力将 React Native 的可行性在项目中产生实际影响。npm
咱们的移动端团队分布在 iOS 和 Android 平台上。swift
团队规模api
最初引入 React Native 时:
到了今天:
在咱们使用 React Native 长达 18 个月的过程当中,咱们的iOS 和 Android 团队的规模都在保持增加。
团队更由一位新的产品经理负责。
咱们经过多名设计师和设计范例进行过转型。
开发背景
引入 React Native 时,使用 Javascript 和 React 范例的每一个团队有多温馨?
iOS
iOS 团队的惟一开发人员以前拥有丰富的 Javascript 和 Web 开发经验,很是乐意使用 React Native 开发。
现在,四个 iOS 开发者中至少有三个习惯并适应使用 Javascript 和 React Native 技术。
Android
在引入 React Native 时,两位 Android 开发人员中有一位对 Javascript 感到满意。另外一位(也就是我本身)只有不多的Javascript,React 或 web 开发背景。
后来加入团队的其余 Android 开发人员也几乎没有 Javascript 或 Web 经验。
咱们的产品是作什么的?
咱们的手机应用旨在为将 Udacity 学习体验带到你的手机设备上。它们支持身份验证,内容发现,程序注册(在某些状况下还有支付),最后支持各类程序和内容类型的学习材料的消费。
这些应用也是新的实验性功能和计划的试验场所,目的在于改善用户的总体学习效果。
代码库规模
同等
引入 React Native 后,应用程序的功能也很是接近。
随着时间的推移,核心体验大体至关,但每一个团队都增长有或多或少的对另外一个平台的经验。
此外,因为国际需求的扩大,本地化和更小的 apk size 等成为 Android 团队愈来愈重视的事情。Android 团队还与其余地区的团队密切合做,针对非 iOS 须要考虑的市场特定功能。
咱们为何要引入?
咱们开始推出全新的移动端专有功能。咱们但愿在两个平台上快速进行实验和验证,所以跨平台开发很是具有吸引力。
由于它是一个新的而且独立的功能,因此被认为是尝试跨平台开发的契机。
选择 React Native 有几个缘由:
咱们是如何引入的?
最初的 React Native 功能是在一个单独的 GitHub 仓库中构建的,并做为 git 子分支分别并入 iOS 和 Android 仓库。
这样能够实现很是快速的原型设计,而且若是须要,能够将该功能做为独立产品发布。
更多的经验是原型,最终咱们在 React Native 代码库中引入了第二个更大的功能。
时间线
答案直截了当。
咱们从应用程序中删除最后的 React Native 代码,由于惟一剩下的 React Native 开发的功能已经下线,咱们再也不须要支持。
“为何咱们中止投入 React Native ?”
这是一个更有趣的问题。
想到下面几点缘由:
咱们已经部署和删除的 React Native 相关功能再也不须要支持,天然不须要替代者。
咱们进军 React Native 的哪些方面进展顺利?
在咱们使用 React Native 期间,咱们遇到了许多问题。其中一些归因于咱们的工做流程,一些归因于咱们的用例,而另外一些则归因于 React Native 自己。
设计和体验的挑战
平台一致的UI / UX
由于咱们将一些新的屏幕集成到现有更大的用户体验当中,因此咱们但愿新的 React Native 代码可以遵循原平生台模式和现有样式。这意味着咱们不必定能为两个平台使用相同的 UI 设计。
在 React Native 中确保每一个平台自身的样式并不困难,但它确实须要了解每一个代码库中使用的设计范例。最简单的是,这须要平台检查以及每一个系统的自定义小部件。
对于咱们来讲,这一般须要与每一个平台的开发人员和设计人员沟通,来了解所须要的内容,或者二者都使用单同样式。这一般会致使 Android 方面的体验与其余应用大相径庭。
一些更复杂的状况下,须要额外的开发平台特定代码来自定义应用体验。
这样的例子之一是确保返回/前进按钮图标的适配。因为须要将新的 React Native 功能集成到现有应用当中,为确保返回/前进图标和返回按钮按下的正确行为,须要针对 React Native 代码库修改 Android 特定原生代码。
原生设计的更改可能须要更改 React Native 代码以处理集成点
不止一次,Android 应用的导航结构发生变化,这要求咱们更新React Native 代码。
React Native 功能没必要被隔离到本身的 Activity 中,而是必须移动到一个 fragment 中,放置在一个带有BottomNavigationView 的屏幕中,而后在它本身和其余原生 fragments 之间协调。
这种类型的平台修改须要返回到单独的代码库,进行更改,更新集成,并确保新修改也不会对 iOS 平台产生负面影响。
设备特定问题
“碎片化”也好,“多样化”也罢,不论你怎么称呼,留给咱们一个不争的事实是有更多独特的 Android 设备配置须要特殊考虑。
咱们屡次发现布局不适应不一样尺寸的 Android 手机。咱们发如今最新的 iPhone 或 Pixel 设备上运行流畅的动画,在 Android 普遍使用的国际市场的低端设备上却运行不佳。
这些确定不是惟一的 React Native 问题;这些是 Android 上常见的开发挑战,但随着平台特定检查和考虑因素的增长,咱们不得不开始考虑使用 React Native 实际节省了多少时间。
全球增加
在咱们使用 React Native 的过程当中,国际化成为 Android 团队的一个更大的挑战。咱们有几个国际办事处要求实现本地化并减小 apk 大小。
React Native 中的字符串本地化能够完成,由于它确实须要额外的设置。在咱们的例子中,它须要更改单独的仓库。这增长了本地化任务的复杂性,这在寻求其余团队的本地化帮助时并不理想。这直接减小了 React Native 功能的本地化频率。
咱们可以在这段时间减小咱们的 apk 大小,可是包含 React Native 的代码规模至关大,咱们没法解决这些问题。删除最后一个 RN 功能后,咱们的 apk 减少 10M 左右,包括资源删除和 React Native 自己的剔除。
集成挑战
与原生组件和导航结构集成
根据咱们的经验,若是是一个独立的功能,将 React Native 集成到现有应用程序中可能很是简单,然而若是须要与现有组件紧密集成并与之通讯,则可能会遇到一些挑战。
咱们发现本身常常须要大量的桥接代码实现原生和 React Native 组件之间的通讯。当咱们须要更改 React Native 组件适应咱们的导航层次结构的位置时,相关代码至少须要一次更新。
工具/构建问题
将 React Native 所需的更新合并到每一个应用的构建过程当中。咱们使用 CircleCI (持续集成工具)来构建咱们须要从新配置的项目,以支持额外的 React Native 构建步骤。
就像前面说的那样,在 Android 方面,这并不像咱们想象的那样简单。
一旦咱们的构建须要更新包含所需的 React Native 任务时,CircleCI 的发布编译时间增长大约20%。
从咱们的代码库中删除最终的 React Native 功能后,咱们看到了如下提高:
Android 团队也遇到过 Android/Gradle 构建工具与 React Native 冲突的问题。最近咱们一直在解决 Gradle 4 版本的问题。
iOS 团队也面临着至关大的挑战。
配置构建很是痛苦,由于咱们的 React Native 的文件结构并不标准。鉴于咱们独立的项目仓库,咱们从 srcroot/ReactNative 拉取 React Native 代码,而且许多现有的构建工具采用了默认的 app 结构,即 /ReactNative/ios/... ios。
此外,咱们使用 cocoapods 进行依赖管理,这是最初建议的融入 React Native 的方式,但在后续已被弃用。咱们非标准的文件结构进一步加重这种状况,致使咱们不得不在 Podfile 中包含一些使人讨厌的黑客式操做,以便能从正确的位置读取到。
因为 cocoapods 再也不是包含 React Native 的规范方式,所以 Podfile 更新依赖于要社区去更新,这并不老是同步的。在几个版本中,css/Yoga 依赖更新掉了,可是 Podfile 却引用了一个不正确的版本... 最后没办法,咱们使用一些黑科技手段解决这种问题。
最后,iOS 项目的 CI(持续集成)也是一个痛点。咱们如今必须添加一个 npm 依赖层,并确保在继续安装以前正确更新它们。这为咱们的构建步骤增长大量的时间。
还有一个引起崩溃的问题,由于一个包含 package.lock
文件的 npm 版本,而另外一个版本没有包含,致使咱们在 React Native 升级过程当中安装了不正确的依赖版本。
文档
React Native 做为一个生态一直在快速发展,咱们发现文档常常跟不上。特别是在咱们首次采用时,咱们发现特定版本的文档/答案可能关联不上。
关于集成 React Native 到现有项目的文档在当时彷佛不多。这是咱们更新 CI 构建所面临挑战的一个因素。
随着 React Native 不断发展,文档和支持社区的贡献获得了改善。若是咱们今天开始,咱们可能会更容易找到一些问题的答案。
导航
咱们最初使用的是 NavigationExperimental,它不是最容易使用的导航库。当 ReactNavigation 出现时,它迅速成为社区普遍接受的导航,而且在 ReactNavigation 真正彻底成熟以前NavigationExperimental 已经被废弃。
性能
如前所述,有些时候会注意到一些性能问题。
咱们可以制做一些很是漂亮的动画,这些动画在规范的 iOS 和 Android 设备上看起来很是不错,但在国际市场上比较广泛的低端 Android 设备上却表现不佳。
进入应用的 React Native 部分时,加载时间比咱们想要的要长。看上去每每不像是无缝过渡。
在对独立功能4进行原型设计时,绘制渲染性能是一个很是大的问题,以至 React Native 被放弃来达到支持原生体验。
滞后于原平生台
由于它不是与 iOS 或 Android 一块儿构建的,因此 React Native 有时会落后于原平生台。它一般很大程度上依赖于社区来支持新的原生功能。
其中一个例子就是迫切须要为 iPhone X 设备提供 SafeArea
支持。咱们最终选择在短期内不使用 SafeArea
支持该功能。使用 SafeAreaView
是跨平台开发人员须要了解的开发兼容应用程序的平台特定功能的一个示例。
在其余时候,React Native 在采用新平台要求方面落后,例如要求在 2018 年 8 月以前针对 api 26 开发 Android 应用程序。这个需求尚有几个未解决的问题。
打破更新
React Native 的非向后兼容升级很是使人沮丧。一个例子是当React Native 升级它的底层 React 库时 PropType 被弃用。
若是再也不维护咱们本身的自定义分支,许多第三方库就会变得没法使用。
维护代码库的 React Native 部分有时对咱们来讲是一个挑战。如前所述,Android 一般须要额外的工做,不管是与现有代码集成仍是修复 UI 适配问题。这致使 iOS 和 Android 在 React Native 代码库的不一样分支上工做,所以一个平台不会减慢另外一个平台的步伐。
因为这种分支,代码的分歧开始慢慢造成,而且使它们达到奇偶校验所需的努力有所增长。结果,对一个平台的更新没有当即添加到另外一个平台。
React Native 的变化速度也带来了挑战。因为可能会破坏更改,所以更新依赖项以获取新功能或错误修复并不老是很快。
一样,有时这会致使冲突增长,从而减慢代码的维护速度。因为团队规模小,精力有限,若是它不是 React Native 代码中的简单/快速修复,因为可能须要额外的开发工做,它的处理可能性要低得多。
添加 React Native 以后,并不老是清楚错误存在于什么级别。它是否存在于两个平台中?仍是只在一个平台上?若是仅在一个平台上,是在原生代码仍是 React Native 代码中?这些问题增长的复杂性有时会减慢质量保证过程。
当须要修复代码库的 React Native 部分中的问题时,咱们如今必须同时考虑iOS 和 Android,而且可能使用3个开发堆栈而不是1个。
此外,只有不到100%的团队感受 React Native 效率很高,可以迅速进入并修复某些东西的开发人员的数量也减小了。
我相信咱们遇到的一些问题是咱们的用例所特有的,可是咱们能够作些不一样的事情来缓解其中的一些问题。
减小分歧
咱们本能够更好地保持每一个应用程序与 React Native repo 中的最新更改保持同步。我相信保持这些更新同步将有助于加强咱们为这些功能开发更强的真正的跨平台开发。
在更多的设备上测试,特别是在 Android 上,这样可以在早期发现更多 UI / 性能问题,并容许咱们在上线以前修复它们。经过在新需求开始工做以前解决问题,这也能够减小代码分歧的数量。
更一致的设计
从一开始就更具体的设计方案可能会改善功能的原生外观。其中一个具体示例是使用与其余原生应用程序一致的文本/边距值,而不是在新体验中选择新值并在两个平台上使用它。
更好的团队理解
对 React Native 不太熟悉的团队成员可能已经作了更多努力以适应额外的开发任务。这会增长可以快速解决代码问题的人数。
我相信咱们团队中没有任何人认为 React Native 没有它的优势。我固然相信 React Native 很是适合用例。
你是否须要在两个平台上快速从头开始构建/构建新应用程序?
你是否正在构建一个应用程序/功能,不管平台如何,其外观/行为都相同?
你有没有想要为移动设备贡献的备用开发周期的 Javascript 开发人员?
若是对这些问题中的任何一个回答“是”,React Native 多是你的可行性选择。
特别是,我认为若是你有 Javascript/React 的背景,而且正在寻找构建一个不须要太多原生代码的应用程序,那么 React Native 是一个很是有吸引力的选择。它将使您可以开始在移动设备上构建,而无需学习2种不一样的技术栈。
对于彻底跨平台应用程序的开发,React Native 也是一个很好的选择。
iOS 和 Android 团队在方面意见不一。
iOS
有可能。iOS 团队一般很高兴与 React Native 合做,并考虑使用它构建新功能。此外,在产品方面,咱们产品经理对在 iOS 上运行的 React Native 解决方案比对 Android 更有信心。
Android
不会。理想状况下,Android 团队未来不会投入精力到 React Native。咱们发现与 React Native 组件集成的过程很麻烦,而且感受到全部 Android 设备的体验都不是很好。
此外,还有一种倾向于坚持单一开发技术战的感受,而不是在Android 框架之上添加新的抽象层和可能的 bugs。
咱们的感受是,React Native 在 Android 上运行新功能的速度更快,但从早期阶段到完美版本再到长期维护须要更长的时间。
做为一个团队,咱们可能不会在不久的未来投入跨平台开发。iOS 团队可使用 React Native 构建一些东西,而且仍然限定于iOS,由于他们团队一般更喜欢这种体验。
我的而言,团队成员会继续关注 React Native 和 Flutter。随着 React Native 和 lutter 等解决方案的不断发展,咱们将继续为咱们的团队评估它们。
这就是咱们今天所处的境地。
咱们对 React Native 如何适应咱们的团队和路线图有了更好的理解。咱们能够利用这些信息为咱们团队的正确技术选择作出明智的判断。
“咱们可否明确地说出 React Native 是否适合你?没有。”
咱们看到了 React Native 的优势以及局限性。咱们可否明确地说出 React Native 是否适合你?
没有。
可是,在评估 React Native 是否适用于你的项目时,但愿咱们的经验能够做为帮你带来一些额外参考点。
相关推荐: 除了Java,为何你还须要学Kotlin? Airbnb 宣布弃用 React Native!
关于我:亦枫,博客地址:yifeng.studio/,新浪微博:IT亦枫
微信扫描二维码,欢迎关注个人我的公众号:安卓笔记侠
不只分享个人原创技术文章,还有程序员的职场遐想
彩蛋:公众号回复关键字“面试资料”,获取 BAT 面试大牛为你准备的全套面试资料!
![]()