非死book:我们是如何构建第一个跨平台的React Native APP

jopen 9年前

今年早些时候,我们介绍过iOS版的React Native. React Native带来的是用web方式的React - 自声明式的UI组件和快速的开发迭代来完成手机平台的功能,然后为了保持速度、保真性、并达到原生的体验。今天我们很高兴发布React Native的Anroid版本.

在非死book我们已经应用React Native在发布的产品有超过一年的时间了。几乎是整整一年之前,我们的团队开始规划开发广告管理APP。 我们的部门是创建一个新的APP来让数百万的非死book广告主来管理他们的账号并能创建新的广告。在完成的时候,这不仅仅是FB的第一个全 React Native APP而且是第一个跨平台的APP.在这篇文章里,我们希望能和你分享我们是如何构建这个APP,React Native是如何让我们更快的,还有这个过程中我们的经验。

选择React Native

不久前,React Native还是一项新的技术,还没有被一款正式的产品应用过。并且开发这样一个新的APP会有很大的挑战,它超过了潜在的好处。

首先,我们初始的团队里有三个产品工程师已经对React很熟悉。另外,这个APP需要处理大量复杂的商业逻辑和精确的处理不同的广告格式、时区、 日期格式、货币、汇率等等诸如此类。而大部分已经用JavaScript来实现了。全部用Objective-C编码并稍后用java实现Android 版本的想法也并没有被赞成,而且也并不高效。第三,用React Native将会很容易来实现大部分的UI,可以实现带数据的列表、表格、图表。产品工程师可以很快的实现这些效果,用React就可以了。

当然,一些特性的实现存在着挑战 - 比如,图片的编辑,用来让广告主缩放和剪切图片;地图视图,用来让广告主设定地理范围。另外一个是面包屑导航,帮助广告主来可视化的知道自己的层级位置。这些都提供机会让我们来推动这个平台的发展。

非死book:我们是如何构建第一个跨平台的React Native APP
非死book:我们是如何构建第一个跨平台的React Native APP

首先实现广告工具的iOS版本

我们的团队觉得首先开发iOS版本,也是为了和React Native的iOS版本校准一致。我们从后面的几个月时间里从3个增加到8个工程师。新加入的成员对React并不熟悉 - 其中也并不熟悉JavsScript - 但是他们都渴望构建一个伟大的手机应用来服务广告主,并且他们成长的非常快。

有经验React Native的iOS工程师帮助我们实现一些他们并没有在React Native中实现的特性,像提供访问相册。他们也帮助我们和其它FB已经存在的APP在使用的iOS库做关联,像认证、分析、崩溃报告、网络和推送提 醒。这让我们的团队可以关注在产品上。

除了上面提到的,我们可以使用以前就写好的JavaScript类库。像Relay,一个通过GraphQL来 传递数据到React应用的FB框架.另外的一系列库用来处理国际化和本地化,它能很聪明的实现时区和货币的调用。这些库的加载是在一个JSON的配置文 件里,包括APP用到的iOS的本地关联文件,仅仅暴露很少的native代码。这让我们的库几乎不需要修改就能使用。

我们遇到的最大的挑战就是导航。为了导航广告主的广告和活动,我们想使用面包屑导航条。指引广告的创建流程,我们需要一个导向式的导航条。在最上面,非常重要的是需要使用合适的动画和手势操作,否则这个APP看起来还是像一个经过美化的website.

我们的解决方案是使用导航组件, 是一个用React Native来实现的可定制化的组件。本质上,它是一个追踪一系列React组件的组件。它可以在组件之间基于按钮点击和按下时进行动画切换。它也具有可 插拔式的导航组件,让我们来实现iOS风格的导航视图,以面包屑的方式来导航广告和活动,指引创建流程的步骤。这个导航条组件还能获取到动画的进度以及根 据需要来调整动画的频率。这意味这所有动画,包括视图和导航条都可以通过JS来处理,而且测试的结果是仍然能够达到60fps.

非死book:我们是如何构建第一个跨平台的React Native APP

只有一种情况下动画才会卡顿,就是当JS线程被一个大的操作占用时。当我们遇到这种情况时,基本上都是执行大量的数据获取操作造成的。必然的,当导 航到新页面时需要加载大量的数据。当网络足够快是,动画可以很容易的被执行。我们的解决方案是延迟数据的获取直到动画执行完毕,这时就使用到了InteractionManager组件,同样是React Native的一部分。我们首先动画到一个新的视图,然后再用Relay来执行数据加载进程,这样就能自动的让需要的React组件实现自动渲染了。

开发Android版本

当iOS版本的广告管理工具接近开发完成时,我们开始着手Android版本的APP.移植React Native的Android是最好的方式来完成这个工作。幸运的是,React Native团队已经在上面做了很多的工作。自然的,我们想尽可能的复用更多的代码,因为大部分的视图都很相似。当然,也有一些地方需要做Android 个性化处理来和iOS版本有所区别,比如,导航的元素或者是调用本地的UI元素像日期选择、开关等等。

非死book:我们是如何构建第一个跨平台的React Native APP

幸运的是,React Native包的黑名单特性和React的抽象结构帮助我们最大化的重用代码来实现跨平台的功能。在iOS版本里,我们打包的时候忽略所有后缀名 为.android.js的文件。对Android的开发,忽略掉所有后缀名为.ios.js的文件。现在我们可以实现同样的组件来同时应用 Android和iOS,也可以个性化的编码在不同平台。替换掉 if/else 这种方式来判断平台,我们尝试重构每个平台的特定UI,这样就可以有Android和iOS的不同实现。在构建Android版本的过程中,大约85%的 代码可以被复用。

另外一个挑战是怎么管理源代码的问题。Android和iOS的代码库在非死book两个不同仓库。广告管理工具的iOS源代码在iOS仓 库,Android版本的代码在Android的代码库。举例来说,像iOS版本的代码,我们想用一些非死book的Android的依赖库,这些库 却在Android的代码库存放。另外,Android的APP所有的编译工具,自动化,以及引入的其它插件都在Android的仓库。基于上 面,Android的这些app要求重构这些已经存在的iOS代码来抽象具体平台的组件来调用各自的文件。我们是可以直接合并两个版本的代码到一起。但是 这种方式却是我们不能接受的。

最后,我们决定指定iOS库为事实上的源代码库,因为iOS版本已经相对稳定。我们设定了定时任务许多次一天来同步iOS的JavaScript到 Android的代码库。我们不鼓励在Android版本提交JavaScript代码,如果提交也是在iOS版本同步的提交一份。如果同步代码发现代码 有差异,会记录一个任务用来进行后续的检查。

我们让iOS仓库的JavaScropt打包成可以在Android版本上运行的代码。这样我们的产品开发人员就可以接触到尽可能多的 JavaScript代码而没有原生代码,也可以直接在iOS仓库直接修改和调试两个版本的代码。但是如果要构建Android的APP还是需要在 Android仓库来执行,同样的操作也会在iOS APP - 测试两个平台的不同需要大量的额外工作。为了提高JavaScript开发者的工作流程,我们同样构建了脚本来下载合适的来自整合服务器的原生文件。对于 大部分开发者来说就不需要复制一份Android的代码库了 - 他们就可以在iOS代码库开发完整的JavaScript代码,并且能比在非死book的web流程中更快速的进行迭代。

我们学到的

React Native团队开发的进程和我们的APP一起,并且和他们一起调试本地化组件和API。这些组件将会为每个构建APP的人带来帮助。尽管我们必须自己来 构建一些组件,用React Native代替纯原生的方式仍然是有价值的。我们不得不需要写这些组件,虽然在未来的一段时间里也可能不会被其它团队再次使用。

学到的另外一课是在分开的iOS和Android代码仓库工作是一件困难的事情,尽管使用了大量的工具和自动化。在构建APP的过程 中,非死book用过这样的模式,我们所有构建的自动化和开发进程都建立并围绕着它。然而,对于产品来说,用一份共享的JavaScript代码库, 这种方式并不好。幸运的是,非死book已经对所有平台都统一了代码库 - 只需要一份JavaScript的拷贝,同步那样的方式已经成为了过去。

另外学到的是关于测试。当做了修改,每一个工程师一定要在所有平台仔细测试,这个过程很容易出现人为的错误。但是开发一个跨平台的APP而且是用一 套代码,这些是必须的。即便如此,由于测试不足导致的成本,远大于用React Native开发的成本和能重用跨平台代码的成本。请记住,这里说的不仅仅是产品工程师;同样包括React Native平台的Objective-C和Java工程师.他们的工作不是限制在原生语言。同样包括JavaScript - 举例来说,组件API和部分分享部分的实现。ISO工程师一般来说不必一定要测试修改后的Android的代码,对应Android工程师也是一样。这种 文化缺陷需要我们用时间和努力来消除,随着时间的推移,我们会越来越稳定。

在每次修改整合版本的时候我们也会标记问题。这些标记的东东可以获取iOS版本的问题,同样的对Android也适用,我们连续的整合版本不会在 iOS修改的时候来运行Android的测试,反过来也一样。这样工程师就可以更多精力来解决问题,并且不用经常的来重启APP.

随着上面说的和做的,我们的债算还完了 - 我们可以运行非死book的第一个完全的React Native APP在两个平台上,具有原生体验,同样的JavaeScript工程师团队。他们当中有些还并不熟悉React, 但是他们在5个月之后就开发出了具有原生体验的iOS版本,之后三个月,我们又发布了Android版本。

英文原文(国内或许不能访问)

来自:http://ljinkai.github.io/2015/09/21/非死book-react-native-android/