设为首页 加入收藏

TOP

Facebook 是如何构建首个跨平台 React Native 应用的?(一)
2015-11-10 13:45:33 来源: 作者: 【 】 浏览:6
Tags:Facebook 如何 构建 跨平台 React Native 应用

今年早些时候,我们发布了?React Native for iOS。React Native 将开发者在 web 上所使用的 React — 拥有声明式的自包含组件以及快速的开发周期 — 带到了移动平台, 同时保留了原生应用程序的运行速度、保真度及外观。今天,我们很高兴地发布了?React Native for Android


现在我们已经在 Facebook 的生产环境中使用 React Native 超过一年了。几乎就是一年之前,我们的团队着手开发广告管理应用。当时我们的目标是创建一个新的应用,它能让数以百万计在 Facebook 上做广告的人们能随时随地的管理他们的账户,并创建新的广告。最后的成果不仅仅是 Facebook 第一完全使用 React Native 开发的应用, 而且是首次实现跨平台的一个应用。本文将跟您分享我们是如何构建这个应用的,React Native 是如何是的我们行动更快的,以及我们所积累的教训。


不久之前,React Native 仍然还是一中没有在生产环境中得到验证的新技术。所以利用该技术开发一个新的应用要承担一些风险,不过这些风险已经被其潜在能带来的好处盖过去了。


当然,有些特性对这个新平台而言却是是一种挑战 — 例如图像编辑器,它可以用来给广告主缩放和裁剪一张照片,还有地图视图,它可以用来给广告主在以一个位置为中心的特定半径内定位人员。另外一个例子就是面包屑导航,它能帮助广告主看清楚他们账户中的广告层级。这些都向我们提供了将这个平台推向更远的机会。




我们的团队决定首先实现这个应用的一个 iOS 版本,这样的安排还不多,React Native 一开始也是针对 iOS 而开发的。接下来的几个月我们的团队成员从 3 名工程师发展到了 8 名。新聘人员对 React 不熟悉 — 而他们其中一些人对 java script 也不熟悉 — 但他们都渴望为我们的广告主构建一种优秀的移动体验,所以他们成长得很快。


React Native 团队中有经验的 iOS 工程师帮助我们在 React Native 中桥接了一些终端设备上暂时还用不着的功能特性,比如提供对手机摄像头的访问。他们还帮助我们将已经被应用在其它 Facebook 应用中的,执行用户认证、分析、奔溃报告、网络以及推送通知这些操作的一些 iOS 库,捆绑到了应用。这样就让我们的团队只用去关注构建这个产品。


如上所述,我们能够重用许多之前已经有了的 java script 库。一个这样的库就是?Relay,Facebook 的一个通过?GraphQL?将数据传递到 React 的框架。另外还有一些处理国际化和本地化(这些逻辑在涉及到时间域和货币时会变得有些棘手)的库。通常这些库会从网站的一个 JSON 端点加载正确的配置。我们已经编写了脚本将所有支持的语言导出为 JSON 文件,使用 iOS 的本地化包来引入这些文件,然后拥几行 native 代码就能将 JSON 数据暴露给 java script。这让我们的库几乎不做什么修改就能拿来用。


我们所面对过的比较大一个挑战之一就是导航流。为了对广告主现有的广告和宣传活动进行导航,我们想要有一个导航条。针对广告的创作流程,我们需要一个向导式的导航条。最重要的是,让应用拥有正确的渐变动画以触摸手势也很关键,否则应用感觉上会更像是一个漂亮的移动网站,而不是一个原生应用。


我们的方案就是?Navigator?组件, React Native 的 CustomComponents 目录下附带就有这个东西能拿来用。实质上,它就是一个由其他的 React 组件堆积起来的 React 组件集合. 它可以显示这些组件中的一个组件,并且这些组件会在按下按钮或者发生触摸时动画轮换。它还有一个可插入式的导航条组件, 让我们可以实现一个 iOS 风格的,用于大多数一般视图的导航条,用于导航广告和宣传活动的面包屑导航,以及一个用于创建流程的向导式导航。导航条组件的动画进度条可以接收通知,并且匹配性的显示进度增加的动画。这意味着所有的动画,针对视图的以及针对导航条的,都是用 java script 来进行计算的, 而测试显示我们仍然可以以 60 fps 的帧率执行它们。


YouTube 视频地址:https://youtu.be/a6yJ7M8FoEo?


只有一种情况下导航动画才会有问题,那就是当 java script 线程在一个长操作过程中被阻塞时。这种情况基本都是由处理大量新获取的数据引起的。当然当你切换到新的页面,读取和处理新的数据是不可避免的。在一个网速快的环境下, 这个问题可以用正在加载的导航动画来解决。在这里我们采取另一种方案:在动画完成前,是用 InteractionManager 组件显式延迟数据处理(这个是 Reactive Native 内置的组件)。首先我们先切换到包含模板的页面,然后使用 Relay 来做数据处理,接着他会自动调用必要的 React 组件来重新渲染界面。


既然 iOS 的广告管理器快要部署完成了,我们现在给这个 app 部署一个 Android 版本。使用 Reactive Native 的 Android 移植版应该是最好的选择。幸运的是,Reactive Native 团队已经将 Android 移植版做的够好了。通常我们想尽可能重用代码,不仅是业务逻辑也有 UI,因为大多数页面是基本相同的,为调整样式节省了时间。当然也有一些地方 Android 版的外观和 iOS 版是需要不同的,比如导航,日期选择器和开关按钮等等。


YouTube 视频地址:https://youtu.be/MNNR01NF290


幸运的是,React Native 打包器的黑名单功能和 React 的抽象机制帮助我们尽可能的在两个平台之间复用代码,尽可能减少对平台的检查。对于 iOS,可以告诉打包器忽略以 .android.js 结尾的文件。而开发Android 的时候,则是忽略 .ios.js 结尾的文件。这样,我们就可以对同一个组件用 Android 和 iOS 分别实现一次,而使用组件的代码可以是平台无关的。我们不是显示的用 if/else 的方式来检测平台,而是重构平台相关的UI部分,分割成不同的需要 Android 和 iOS 分别实现的组件。在发布 Android 版广告管理器的时候,代码的复用率达到了大约85%。


我们面临的一个大的挑战是如何管理代码。在 Facebook,Android 和 iOS 的代码在不同的代码仓库里。广告管理器的 iOS 版本的代码在 iOS 代码库里,而由于各种原因,Android 版本的代码只能在 Android 代码库里。就像 iOS 版那样,我们需要使用一些 Android 代码库里的 Facebook 的 Android 库。另外,所有的构建、自动化和持续集成工具都绑定了 Android 代码库。如果把已有的 iOS 版代码重构,抽象出平台无关的组件用于 Android 版的移植,则意味着我们要经常 fork 和 merge 相同的代码的两个不同版本。对我们来说,这种情形不能接受。


最后我们决定把 iOS 代码库当做可信的代码源,主要是因为代码已经存在并且 iOS 版的 App 也已经成熟了。我们通过 cron 的任务每天把所有 java script 代码从 iOS 同步几次到 Android 代码库。直接提交 java script 代码到 Android 仓库是不被允许的,除非同时提交到 iOS 仓库。如果同步脚本检测到有不一致的地方,会生成一个任务,后续去进一步检查。


我们同时还做到了让 java script 打包服务器从 iOS 仓库运行 Android 代码。这

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Python 面向对象编程 下一篇Java中hashcode,equals和==

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: