跳到主要内容

旧金山见面会回顾

·阅读时长 9 分钟
Héctor Ramos
Héctor Ramos
前 Facebook 开发者倡导者

上周我有幸参加了在 Zynga 旧金山办公室举行的 React Native 聚会。约有 200 人参加,这是一个与我身边其他对 React Native 感兴趣的开发者见面的绝佳场所。

我特别感兴趣的是了解 React 和 React Native 如何在 Zynga、Netflix 和 Airbnb 等公司中使用。当晚的议程如下:

  • 在 React 中进行快速原型开发
  • 为 React Native 设计 API
  • 弥合差距:在现有代码库中使用 React Native

但首先,活动以一个简短的介绍和近期新闻的简要回顾开始

  • 你知道 React Native 现在是 GitHub 上最受欢迎的 Java 仓库了吗?
  • rnpm 现在已成为 React Native 核心的一部分!您现在可以使用 react-native link 代替 rnpm link安装带有原生依赖的库
  • React Native Meetup 社区正在快速发展!全球各地的 React Native meetup 小组现在共有超过 4,800 名开发者。

如果其中一个聚会在您附近举行,我强烈建议您参加!

在 Zynga 使用 React 进行快速原型开发

第一轮新闻之后,我们的东道主 Zynga 做了简短介绍。Abhishek Chadha 谈到了他们如何使用 React 快速原型化移动端新体验,并演示了一个类似“你画我猜”的快速原型应用。他们采用了与 React Native 类似的方法,通过桥接提供对原生 API 的访问。当 Abhishek 使用设备相机拍摄观众照片,然后在一个人的头上画了一顶帽子时,这一点得到了证实。

为 Netflix 的 React Native 设计 API

接下来是当晚的第一个专题演讲。Clarence Leung,Netflix 的高级软件工程师,发表了关于“为 React Native 设计 API”的演讲。他首先指出了两种主要类型的库:组件(如标签栏和日期选择器)以及提供访问原生服务(如相机胶卷或应用内支付)的库。在为 React Native 构建库时,有两种方法可以采用:

  • 提供平台特定的组件
  • 一个跨平台库,在 Android 和 iOS 上具有相似的 API

每种方法都有其自身的考量,由您决定哪种最适合您的需求。

方法一

作为平台特定组件的示例,Clarence 谈到了核心 React Native 中的 DatePickerIOS 和 DatePickerAndroid。在 iOS 上,日期选择器作为 UI 的一部分呈现,可以轻松嵌入现有视图中,而 Android 上的日期选择器则以模态形式呈现。在这种情况下,提供单独的组件是有意义的。

方法二

另一方面,照片选择器在 Android 和 iOS 上的处理方式相似。尽管存在一些细微差异,例如 Android 不像 iOS 那样将照片分组到自拍文件夹中,但这些差异都可以通过 if 语句和 Platform 组件轻松处理。

无论您采用哪种方法,最好都能最小化 API 表面并构建特定于应用的库。例如,iOS 的应用内购买框架支持一次性、可消耗的购买以及可续订的订阅。如果您的应用只需要支持可消耗购买,那么您可以在跨平台库中放弃对订阅的支持。

Clarence 的演讲结束后有一个简短的问答环节。其中一个有趣的花絮是,Netflix 为这些库编写的 React Native 代码中约有 80% 在 Android 和 iOS 之间共享。

弥合差距:在现有代码库中使用 React Native

当晚的最后一场演讲由 Airbnb 的 Leland Richardson 发表。演讲的重点是在现有代码库中使用 React Native。我早已知道使用 React Native 从零开始编写新应用是多么容易,所以我对 Airbnb 在其现有原生应用中采用 React Native 的经验非常感兴趣。

Leland 首先谈到了“绿地项目”与“棕地项目”。绿地项目指的是从零开始一个项目,无需考虑任何先前的工作。这与棕地项目形成对比,棕地项目需要考虑现有项目的需求、开发流程以及所有团队的各种需求。

当你在开发一个绿地应用时,React Native CLI 会为 Android 和 iOS 设置一个单一的仓库,所有东西都能正常工作。Airbnb 使用 React Native 面临的第一个挑战是,Android 和 iOS 应用各自拥有独立的仓库。多仓库公司在采用 React Native 之前需要克服一些障碍。

为了解决这个问题,Airbnb 首先为 React Native 代码库设置了一个新的仓库。他们使用持续集成服务器将 Android 和 iOS 仓库镜像到这个新仓库中。在运行测试并构建捆绑包后,构建产物会同步回 Android 和 iOS 仓库。这使得移动工程师可以在不改变其开发环境的情况下处理原生代码。移动工程师不需要安装 npm、运行打包器,也不需要记住构建 JavaScript 捆绑包。编写实际 React Native 代码的工程师不必担心跨 Android 和 iOS 同步他们的代码,因为他们直接在 React Native 仓库中工作。

这确实带来了一些缺点,主要在于他们无法发布原子更新。需要原生代码和 JavaScript 代码组合的更改将需要三个独立的拉取请求,所有这些都必须仔细合并。为了避免冲突,如果在构建开始后主分支发生更改,CI 将无法将更改合并回 Android 和 iOS 仓库。这将在高提交频率的日子(例如发布新版本时)导致长时间的延迟。

Airbnb 从那时起已转向单一代码库方法。幸运的是,这已经考虑在内,一旦 Android 和 iOS 团队对使用 React Native 感到满意,他们便乐于加速向单一代码库的迁移。

这解决了他们在使用分离仓库方法时遇到的多数问题。Leland 确实指出,这确实会给版本控制服务器带来更大的压力,这对于小型公司来说可能是一个问题。

导航问题

Leland 演讲的后半部分聚焦于一个我非常关心的话题:React Native 中的导航问题。他谈到了 React Native 中大量的第一方和第三方导航库。NavigationExperimental 被提及为一个看起来很有希望的东西,但最终发现不适合他们的用例。

事实上,现有导航库似乎都没有很好地适用于“棕地应用”。“棕地应用”要求导航状态完全由原生应用拥有。例如,如果用户会话在 React Native 视图显示期间过期,原生应用应该能够接管并根据需要显示登录屏幕。

Airbnb 还希望避免在过渡期间用 JavaScript 版本替换原生导航栏,因为这种效果可能会让人感到不协调。最初他们将自己限制在模态呈现的视图,但这显然在他们的应用中更广泛地采用 React Native 时带来了问题。

他们决定他们需要自己的库。这个库叫做 airbnb-navigation。该库尚未开源,因为它与 Airbnb 的代码库紧密相关,但他们希望能在今年年底发布它。

我不会详细介绍该库的 API,但以下是一些要点:

  • 必须提前预注册场景
  • 每个场景都显示在自己的 `RCTRootView` 中。它们在每个平台上以原生方式呈现(例如,iOS 上使用 `UINavigationController`)。
  • 场景中的主 `ScrollView` 应该用 `ScrollScene` 组件包裹。这样做可以利用原生行为,例如在 iOS 上点击状态栏滚动到顶部。
  • 场景之间的过渡由原生处理,无需担心性能。
  • Android 返回按钮自动支持。
  • 他们可以通过 Navigator.Config 无 UI 组件利用基于视图控制器的导航栏样式。

还有一些注意事项需要牢记:

  • 导航栏不易在 JavaScript 中自定义,因为它是原生组件。这是故意的,因为使用原生导航栏是此类库的硬性要求。
  • ScreenProps 在通过桥接发送时必须序列化/反序列化,因此在此处发送过多数据时必须小心。
  • 导航状态由原生应用拥有(也是库的硬性要求),因此 Redux 等工具无法操作导航状态。

Leland 的演讲之后还有问答环节。总的来说,Airbnb 对 React Native 很满意。他们对使用 Code Push 来修复任何问题而无需通过 App Store 感兴趣,他们的工程师喜欢 Live Reload,因为他们不需要在每次细微更改后等待原生应用重新构建。

结束语

活动以一些额外的 React Native 新闻结束

聚会提供了一个与社区中其他开发者见面并学习的好机会。我期待着未来参加更多的 React Native 聚会。如果您能参加其中一个,请留意我,让我知道我们如何能让 React Native 更好地为您服务!

迈向更好的文档

·阅读时长5分钟
Kevin Lacker
Facebook 工程经理

拥有良好开发者体验的一部分是拥有出色的文档。创建良好文档需要付出很多努力——理想的文档是简洁、有用、准确、完整且令人愉悦的。最近我们一直在根据您的反馈努力改进文档,我们想分享一些我们所做的改进。

内联示例

当你学习一个新的库、一种新的编程语言或一个新的框架时,会有一个美好的时刻:你第一次编写一点代码,尝试它,看看它是否有效……而它确实有效。你创造了真实的东西。我们希望将这种直观的体验直接融入到我们的文档中。就像这样

import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

class ScratchPad extends Component {
render() {
return (
<View style={{flex: 1}}>
<Text style={{fontSize: 30, flex: 1, textAlign: 'center'}}>
Isn't this cool?
</Text>
<Text style={{fontSize: 100, flex: 1, textAlign: 'center'}}>
👍
</Text>
</View>
);
}
}

AppRegistry.registerComponent('ScratchPad', () => ScratchPad);

我们认为这些使用 react-native-web-player 模块(在 Devin Abbott 帮助下)的内联示例是学习 React Native 基础知识的好方法,我们已经更新了面向新 React Native 开发者的教程,尽可能地使用这些示例。快来看看吧——如果你曾好奇修改一小段示例代码会发生什么,这是一个很好的探索方式。此外,如果你正在构建开发者工具并想在自己的网站上展示一个实时的 React Native 示例,react-native-web-player 可以让这变得简单。

核心模拟引擎由 Nicolas Gallagherreact-native-web 项目提供,该项目提供了一种在网络上显示 React Native 组件(如 TextView)的方式。如果您有兴趣构建共享大量代码库的移动和网络体验,请查看 react-native-web

更好的指南

在 React Native 的某些部分,有多种方法可以完成事情,我们收到了反馈,认为我们可以提供更好的指导。

我们有一个新的导航指南,它比较了不同的方法并就您应该使用什么(NavigatorNavigatorIOSNavigationExperimental)提供了建议。在中期,我们正在努力改进和整合这些接口。在短期内,我们希望一个更好的指南能让您的生活更轻松。

我们还有一个新的处理触摸指南,它解释了制作类似按钮界面的基础知识,以及处理触摸事件的不同方法的简要总结。

我们努力的另一个领域是 Flexbox。这包括关于如何使用 Flexbox 处理布局以及如何控制组件大小的教程。它还包括一个不起眼但希望能有用的React Native 中所有控制布局的 props 列表

开始使用

当你在你的机器上开始设置 React Native 开发环境时,你确实需要安装和配置很多东西。让安装成为一个真正有趣和令人兴奋的体验是很困难的,但我们至少可以使其尽可能快速和无痛。

我们构建了一个新的入门工作流,让您可以预先选择您的开发操作系统和移动操作系统,在一个简洁的地方提供所有设置说明。我们还仔细检查了安装过程,以确保一切正常工作,并确保每个决策点都有明确的建议。在我们的无辜同事身上测试后,我们非常确定这是一个改进。

我们还完善了将 React Native 集成到现有应用中的指南。许多使用 React Native 的大型应用,例如 Facebook 应用本身,实际上是部分使用 React Native 构建,部分使用常规开发工具。我们希望本指南能让更多人更容易地以这种方式构建应用。

我们需要您的帮助

您的反馈让我们知道我们应该优先处理什么。我知道有些人会读完这篇博文然后想:“更好的文档?哼。X 的文档还是垃圾!”。这太棒了——我们需要这种能量。给出反馈的最佳方式取决于反馈的类型。

如果您在文档中发现错误,例如不准确的描述或无法正常工作的代码,请提交问题。将其标记为“Documentation”,以便更容易地将其路由给合适的人。

如果不是特定的错误,而是文档中的某些内容根本上令人困惑,那么它就不太适合 GitHub Issue。相反,请在 Canny 上发布有关需要帮助的文档区域。这有助于我们在进行更一般的文档编写工作时确定优先级。

感谢您阅读到这里,也感谢您使用 React Native!

React Native:一年回顾

·阅读时长2分钟
Martin Konicek
Facebook 软件工程师

自我们开源 React Native 以来,已有一年。最初只是少数工程师的一个想法,现在已成为 Facebook 内外产品团队都在使用的框架。今天在 F8 大会上,我们宣布 Microsoft 将把 React Native 带到 Windows 生态系统,让开发者有机会在 Windows PC、手机和 Xbox 上构建 React Native 应用。它还将提供开源工具和服务,例如适用于 Visual Studio Code 的 React Native 扩展和 CodePush,以帮助开发者在 Windows 平台上创建 React Native 应用。此外,三星正在为其混合平台构建 React Native,这将使开发者能够为数百万智能电视以及移动和可穿戴设备构建应用。我们还发布了 适用于 React Native 的 Facebook SDK,这使得开发者更容易将 Facebook 社交功能(如登录、分享、应用分析和 Graph API)整合到他们的应用中。一年之内,React Native 改变了开发者在每个主要平台上构建应用的方式。

这是一段史诗般的旅程——但我们才刚刚开始。以下回顾了 React Native 自一年前开源以来是如何成长和演变的,我们在此过程中遇到的一些挑战,以及我们对未来的展望。

这是一篇节选。阅读完整文章请访问 Facebook Code

深入了解 React Native 性能

·阅读时长2分钟
Pieter De Baets
Facebook 软件工程师

React Native 允许您使用 React 和 Relay 的声明式编程模型,用 JavaScript 构建 Android 和 iOS 应用程序。这使得代码更简洁,更易于理解;无需编译周期即可快速迭代;并且可以轻松地在多个平台之间共享代码。您可以更快地发布,并专注于真正重要的细节,让您的应用程序看起来和感觉都很棒。优化性能是其中的重要组成部分。以下是我们如何将 React Native 应用程序启动速度提高一倍的故事。

为何急于求成?

应用程序运行得更快,内容加载得也更快,这意味着人们有更多时间与它互动,流畅的动画让应用程序使用起来很愉快。在新兴市场,2011 年的手机2G 网络上占大多数,对性能的关注可以决定应用程序是否可用。

自从在 iOSAndroid 上发布 React Native 以来,我们一直在改进列表视图滚动性能、内存效率、UI 响应能力和应用启动时间。启动决定了应用的第一印象,并对框架的所有部分都造成压力,因此它是最值得解决也最具挑战性的问题。

这是摘录。阅读其余帖子请访问 Facebook Code。

引入热重载

·阅读时长 9 分钟
Martín Bigio
Instagram 软件工程师

React Native 的目标是为您提供最佳的开发者体验。其中很重要的一部分是您保存文件到看到更改所需的时间。我们的目标是使这个反馈循环在应用程序增长时也能保持在1秒以内。

我们通过以下三个主要功能接近这个理想状态:

  • 使用 JavaScript 作为语言,因为它没有漫长的编译周期。
  • 实现一个名为 Packager 的工具,将 ES6/Flow/JSX 文件转换为虚拟机可理解的普通 JavaScript。它被设计为一个服务器,在内存中保存中间状态以实现快速增量更改,并使用多核。
  • 构建一个名为“实时重载”的功能,在保存时重新加载应用程序。

此时,开发者的瓶颈不再是重新加载应用所需的时间,而是丢失应用的状态。一个常见的场景是,在一个距离启动屏幕有多个屏幕的功能上工作。每次重新加载时,你都必须一遍又一遍地点击相同的路径才能回到你的功能,这使得周期长达数秒。

热重载

热重载的理念是保持应用程序运行,并在运行时注入您编辑的文件的最新版本。这样,您不会丢失任何状态,这在调整 UI 时尤其有用。

一图胜千言。看看实时重载(当前)和热重载(新)之间的区别。

如果您仔细观察,您会发现可以从红框中恢复,并且还可以开始导入以前不存在的模块,而无需完全重新加载。

警告:因为 JavaScript 是一种非常依赖状态的语言,热重载无法完美实现。实际上,我们发现目前的设置对于大量常见用例都运行良好,并且在出现问题时始终可以使用完全重载。

热重载在 0.22 版本中可用,您可以启用它:

  • 打开开发者菜单
  • 点击“启用热重载”

实现概述

现在我们已经了解了为什么需要它以及如何使用它,有趣的部分开始了:它实际是如何工作的。

热重载是建立在 Hot Module Replacement (HMR) 功能之上的。它最初由 webpack 引入,我们将其实现到了 React Native 打包器中。HMR 使打包器能够监听文件更改并将 HMR 更新发送到应用程序中包含的一个轻量级 HMR 运行时。

简而言之,HMR 更新包含已更改的 JS 模块的新代码。当运行时收到它们时,它会将旧模块的代码替换为新代码。

HMR 更新不仅包含我们想要更改的模块代码,因为替换它不足以让运行时获取更改。问题是模块系统可能已经缓存了我们想要更新的模块的导出。例如,假设您的应用程序由这两个模块组成

// log.js
function log(message) {
const time = require('./time');
console.log(`[${time()}] ${message}`);
}

module.exports = log;
// time.js
function time() {
return new Date().getTime();
}

module.exports = time;

模块 `log` 打印提供的消息,包括模块 `time` 提供的当前日期。

当应用程序打包时,React Native 使用 `__d` 函数在模块系统上注册每个模块。对于这个应用程序,在许多 `__d` 定义中,会有一个 `log` 的定义。

__d('log', function() {
... // module's code
});

此调用将每个模块的代码包装到一个匿名函数中,我们通常称之为工厂函数。模块系统运行时会跟踪每个模块的工厂函数、它是否已经执行以及执行结果(导出)。当模块被要求时,模块系统要么提供已缓存的导出,要么首次执行模块的工厂函数并保存结果。

所以假设您启动应用程序并需要 log。此时,logtime 的工厂函数都未执行,因此没有缓存导出。然后,用户修改 time 以返回 MM/DD 格式的日期

// time.js
function bar() {
const date = new Date();
return `${date.getMonth() + 1}/${date.getDate()}`;
}

module.exports = bar;

Packager 会将 time 的新代码发送到运行时(步骤 1),当 `log` 最终被 require 时,导出的函数会与 `time` 的更改一起执行(步骤 2)。

现在,假设 `log` 的代码将 `time` 作为顶层 `require`。

const time = require('./time'); // top level require

// log.js
function log(message) {
console.log(`[${time()}] ${message}`);
}

module.exports = log;

当 `log` 被引用时,运行时会缓存它的导出和 `time` 的导出。(步骤 1)。然后,当 `time` 被修改时,HMR 进程不能仅仅在替换 `time` 的代码后就结束。如果它这样做,当 `log` 执行时,它会使用 `time` 的缓存副本(旧代码)执行。

为了让 `log` 接收 `time` 的更改,我们需要清除其缓存的导出,因为其所依赖的模块之一已被热交换(步骤 3)。最后,当 `log` 再次被请求时,它的工厂函数将被执行,请求 `time` 并获取其新代码。

HMR API

React Native 中的 HMR 通过引入 `hot` 对象来扩展模块系统。此 API 基于 webpack 的 API。`hot` 对象公开了一个名为 `accept` 的函数,它允许您定义一个回调,该回调将在模块需要热交换时执行。例如,如果我们将 `time` 的代码更改如下,每次保存 `time` 时,我们都会在控制台中看到“time changed”

// time.js
function time() {
... // new code
}

module.hot.accept(() => {
console.log('time changed');
});

module.exports = time;

请注意,您很少需要手动使用此 API。对于大多数常见用例,热重载应该开箱即用。

HMR 运行时

正如我们之前所见,有时仅仅接受 HMR 更新是不够的,因为使用正在热交换模块的模块可能已经执行并且其导入已被缓存。例如,假设电影应用示例的依赖树有一个顶级 `MovieRouter`,它依赖于 `MovieSearch` 和 `MovieScreen` 视图,而这些视图又依赖于前面示例中的 `log` 和 `time` 模块

如果用户访问电影搜索视图但未访问其他视图,则除 `MovieScreen` 之外的所有模块都将缓存导出。如果对 `time` 模块进行了更改,运行时将不得不清除 `log` 的导出,以便它能够接收 `time` 的更改。这个过程不会就此结束:运行时将递归重复此过程,直到所有父级都被接受。因此,它将获取依赖于 `log` 的模块并尝试接受它们。对于 `MovieScreen`,它可以跳过,因为它尚未被要求。对于 `MovieSearch`,它将不得不清除其导出并递归处理其父级。最后,它将对 `MovieRouter` 执行相同的操作,并在那里结束,因为没有模块依赖于它。

为了遍历依赖树,运行时从 Packager 接收 HMR 更新中的反向依赖树。对于这个例子,运行时将接收一个像这样的 JSON 对象:

{
modules: [
{
name: 'time',
code: /* time's new code */
}
],
inverseDependencies: {
MovieRouter: [],
MovieScreen: ['MovieRouter'],
MovieSearch: ['MovieRouter'],
log: ['MovieScreen', 'MovieSearch'],
time: ['log'],
}
}

React 组件

React 组件更难以与热重载协同工作。问题在于我们不能简单地用新代码替换旧代码,因为那样会丢失组件的状态。对于 React Web 应用程序,Dan Abramov 实现了一个 babel 转换,它使用 webpack 的 HMR API 来解决这个问题。简而言之,他的解决方案通过在转换时为每个 React 组件创建一个代理来实现。这些代理保留了组件的状态,并将生命周期方法委托给实际组件,而这些组件正是我们热重载的对象

除了创建代理组件外,转换还定义了 `accept` 函数,其中包含一段强制 React 重新渲染组件的代码。通过这种方式,我们可以在不丢失任何应用程序状态的情况下热重载渲染代码。

React Native 附带的默认转换器使用 `babel-preset-react-native`,它被配置为以与您在使用 webpack 的 React Web 项目中相同的方式使用 `react-transform`。

Redux Stores

要启用 Redux 存储的热重载,您只需像在使用 webpack 的 Web 项目中一样使用 HMR API:

// configureStore.js
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from '../reducers';

export default function configureStore(initialState) {
const store = createStore(
reducer,
initialState,
applyMiddleware(thunk),
);

if (module.hot) {
module.hot.accept(() => {
const nextRootReducer = require('../reducers/index').default;
store.replaceReducer(nextRootReducer);
});
}

return store;
};

当你更改一个 reducer 时,接受该 reducer 的代码将被发送到客户端。然后客户端会意识到 reducer 不知道如何接受自己,所以它会查找所有引用它的模块并尝试接受它们。最终,流程会到达单一的 store,即 configureStore 模块,它将接受 HMR 更新。

结论

如果您有兴趣帮助改进热重载,我鼓励您阅读 Dan Abramov 关于热重载未来的文章并做出贡献。例如,Johny Days 将使其与多个连接的客户端协同工作。我们依赖大家来维护和改进此功能。

借助 React Native,我们有机会重新思考构建应用程序的方式,以创造出色的开发者体验。热重载只是其中一部分,我们还能做些什么疯狂的“黑科技”来做得更好呢?

让 React Native 应用更易于访问

·阅读时长2分钟
Georgiy Kassabli
Facebook 软件工程师

随着 React 在 Web 和 React Native 在移动端的近期发布,我们为开发者提供了构建产品的新前端框架。构建健壮产品的一个关键方面是确保任何人都可以使用它,包括有视力障碍或其他残疾的人。React 和 React Native 的无障碍 API 使您能够使任何由 React 驱动的体验可供使用辅助技术的人使用,例如盲人和视力障碍者的屏幕阅读器。

本文我们将重点关注 React Native 应用程序。我们将 React Accessibility API 设计成与 Android 和 iOS API 相似的外观和感觉。如果您之前开发过 Android、iOS 或 Web 的无障碍应用程序,您应该会熟悉 React AX API 的框架和命名约定。例如,您可以将 UI 元素设置为“可访问”(因此暴露给辅助技术),并使用“accessibilityLabel”为该元素提供字符串描述。

<View accessible={true} accessibilityLabel=”This is simple view”>

让我们通过查看 Facebook 自己的一个 React 驱动产品:广告管理应用,来了解 React AX API 的一个稍微复杂一些的应用。

这是一个摘录。请在 Facebook Code 上阅读其余内容。

React Native for Android:我们如何构建第一个跨平台 React Native 应用

·阅读时长2分钟
Facebook 软件工程师

今年早些时候,我们推出了适用于 iOS 的 React Native。React Native 将开发者在 Web 上使用 React 所习惯的——声明式、自包含的 UI 组件和快速开发周期——带到了移动平台,同时保留了原生应用程序的速度、保真度和感受。今天,我们很高兴发布适用于 Android 的 React Native。

在 Facebook,我们使用 React Native 进行生产已有一年多。大约一年前,我们的团队着手开发 Ads Manager 应用。我们的目标是创建一个新的应用,让数百万在 Facebook 上投放广告的人可以随时随地管理他们的账户和创建新的广告。它最终不仅成为 Facebook 第一个完全由 React Native 构建的应用,也是第一个跨平台应用。在这篇文章中,我们想与您分享我们如何构建这个应用,React Native 如何使我们能够更快地行动,以及我们学到的经验教训。

这是一个摘录。阅读这篇博文的其余部分,请访问 Facebook Code

React Native:将现代网络技术带到移动端

·3 分钟阅读
Tom Occhino
Facebook 工程经理

两年前,我们将 React 推向世界,从那时起,它在 Facebook 内部和外部都取得了令人瞩目的增长。如今,尽管没有人被迫使用它,但 Facebook 的新 Web 项目通常都以某种形式使用 React 构建,并且它正在行业中广泛采用。工程师们每天选择使用 React,因为它使他们能够将更多时间专注于产品,更少时间与框架作斗争。然而,直到我们用 React 构建了一段时间后,我们才开始理解它如此强大的原因。

React 迫使我们将应用程序分解为离散的组件,每个组件代表一个单一视图。这些组件使得产品迭代更容易,因为我们不需要将整个系统都放在脑中才能修改其中的一部分。更重要的是,React 用声明式 API 封装了 DOM 的变异式、命令式 API,这提高了抽象级别并简化了编程模型。我们发现,使用 React 构建时,我们的代码更具可预测性。这种可预测性使我们能够更快、更自信地迭代,因此我们的应用程序也更加可靠。此外,使用 React 构建的应用程序不仅更容易扩展,我们还发现团队规模本身也更容易扩展。

结合 Web 的快速迭代周期,我们已经能够用 React 构建一些很棒的产品,包括 Facebook.com 的许多组件。此外,我们还在 React 之上构建了令人惊叹的 JavaScript 框架,比如 Relay,它使我们能够极大地简化大规模数据获取。当然,Web 只是故事的一部分。Facebook 还有广泛使用的 Android 和 iOS 应用程序,它们是基于不连贯的专有技术栈构建的。不得不在多个平台上构建我们的应用程序使我们的工程组织分裂,但这只是使原生移动应用程序开发困难的其中一个原因。

这是摘录。请在 Facebook Code 上阅读帖子的其余部分。