英文原文(需FQ):https://code.facebook.com/posts/1189117404435352/

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

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

选择React Native

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

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

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


首先实现广告工具的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.

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

开发Android版本

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

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

另外一个挑战是怎么管理源代码的问题。Android和iOS的代码库在Facebook两个不同仓库。广告管理工具的iOS源代码在iOS仓库,Android版本的代码在Android的代码库。举例来说,像iOS版本的代码,我们想用一些Facebook的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代码,并且能比在Facebook的web流程中更快速的进行迭代。

我们学到的

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

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

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

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

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

程序员专用站立办公桌

点击了解详情

[译] Facebook:我们是如何构建第一个跨平台的 React Native APP的更多相关文章

  1. React Native ios开发第一课

    前言 本篇文章的作用在于帮助你快速上手使用React Native编写iOS应用.如果你现在还不太了解React Native是什么以及Facebook为什么要创建React Native,你可以先看 ...

  2. 从零学React Native之01创建第一个程序

    本篇首发于简书 欢迎关注 上一篇文章是时候了解React Native了介绍了React Native.大家应该对React Native有个初步的认识. 接下来我们就可以初始化一个React Nat ...

  3. qt利用QT designer构建第一个界面helloworld工程

    qt利用QT designer构建第一个界面helloworld工程原创ZJE_ANDY 发布于2017-04-07 20:25:28 阅读数 6613 收藏展开第一步:点击New Project 第 ...

  4. React Native:使用 JavaScript 构建原生应用

    [转载] 本篇为联合翻译,译者:寸志,范洪春,kmokidd,姜天意 数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生 ...

  5. 深入浅出 React Native:使用 JavaScript 构建原生应用

    深入浅出 React Native:使用 JavaScript 构建原生应用 链接:https://zhuanlan.zhihu.com/p/19996445 原文:Introducing React ...

  6. React Native:使用 JavaScript 构建原生应用 详细剖析

    数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生的 iOS 应用——就在今天,Beta 版的仓库释出了! 基于 Pho ...

  7. 移动应用跨平台框架江湖将现终结者?速来参拜来自Facebook的React Native

    React Native使用初探 February 06 2015 Facebook让所有React Conf的参与人员都可以初尝React Native的源码---一个编写原生移动应用的方法.该方法 ...

  8. 看Facebook是如何优化React Native性能

    原文出处: facebook   译文出处:@Siva海浪高 该文章翻译自Facebook官方博客,传送门 React Native 允许我们运用 React 和 Relay 提供的声明式的编程模型, ...

  9. AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX

    AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX 一.什么是JSX 使用JSX声明一个变量(REACT当中的元素): const element =< ...

随机推荐

  1. 系统整理qt笔记3

    qtcreator中不能输入中文: https://blog.csdn.net/qq_15725099/article/details/97305507 main.cpp #include " ...

  2. Flutter 设计模式|工厂模式家族

    文/ 杨加康,CFUG 社区成员,<Flutter 开发之旅从南到北>作者,小米工程师 在围绕设计模式的话题中,工厂这个词频繁出现,从 简单工厂 模式到 工厂方法 模式,再到 抽象工厂 模 ...

  3. gitee的使用

    git clone git add . # 跟踪所有改动过的文件 git commit -m "commit message" # 提交所有更新过的文件 git checkout ...

  4. 从刘维尔方程到Velocity-Verlet算法

    技术背景 我们说分子动力学模拟是一个牛顿力学的过程,在使用量子化学的手段或者深度学习的方法或者传统的力场方法,去得到某个时刻某个位置的受力之后,就可以获取下一步的整个系统的状态信息.这个演化的过程所使 ...

  5. python安装jupyter notebooks(windows下)

    [1]前提 前提:下载好Python并把python添加到了Path路径 以3.8为例子,在安装的时候有个这个勾选项,Add Python 3.8 to PATH,勾上就好,没有的话.就把python ...

  6. Java的jmap命令使用详解

    jmap命令简介 jmap(Java Virtual Machine Memory Map)是JDK提供的一个可以生成Java虚拟机的堆转储快照dump文件的命令行工具.除此以外,jmap命令还可以查 ...

  7. Python入门随记(4)

    在涉及一些实际问题,会碰到概率论等相关领域的知识,自然少不了矩阵运算,以下是Python中关于矩阵的简单操作: 1.常用库numpy import numpy as np 2.随机生成矩阵 a=np. ...

  8. 高级IO模型之kqueue和epoll

    目录 简介 block IO和nonblocking IO IO多路复用和select poll epoll kqueue epoll和kqueue的优势 简介 任何一个程序都离不开IO,有些是很明显 ...

  9. 4月4日 python学习总结 os pickle logging

    1.序列化和反序列化 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling. 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickl ...

  10. python 发送POST请求

    #博客地址:https://blog.csdn.net/qq_36374896 import urllib.request import urllib.parse url = "http:/ ...