跳过主内容

将 AWS 与 React Native 结合使用

·阅读 10 分钟
Richard Threlkeld
AWS 移动部门高级技术产品经理

AWS 在科技行业是众所周知的云服务提供商。这些服务包括计算、存储和数据库技术,以及完全托管的无服务器产品。AWS 移动团队一直与客户和 JavaScript 生态系统的成员密切合作,使云连接的移动和 Web 应用程序更加安全、可扩展,并且更易于开发和部署。我们最初提供了一个完整的入门工具包,但最近又有一些新的发展。

这篇博客文章讨论了 React 和 React Native 开发者关注的一些有趣内容

  • AWS Amplify,一个用于使用云服务的 JavaScript 应用程序的声明式库
  • AWS AppSync,一个具有离线和实时功能的完全托管的 GraphQL 服务

AWS Amplify

使用 Create React Native App 和 Expo 等工具,React Native 应用程序的引导过程非常简单。然而,当您尝试将用例与基础设施服务匹配时,将其连接到云可能难以操作。例如,您的 React Native 应用可能需要上传照片。这些照片是否应该按用户进行保护?这可能意味着您需要某种注册或登录过程。您想要自己的用户目录还是使用社交媒体提供商?也许您的应用在用户登录后还需要调用带有自定义业务逻辑的 API。

为了帮助 JavaScript 开发者解决这些问题,我们发布了一个名为 AWS Amplify 的库。其设计被分解为任务的“类别”,而不是 AWS 特定的实现。例如,如果您希望用户注册、登录,然后上传私人照片,您只需将 AuthStorage 类别引入您的应用程序即可

import { Auth } from 'aws-amplify';

Auth.signIn(username, password)
.then(user => console.log(user))
.catch(err => console.log(err));

Auth.confirmSignIn(user, code)
.then(data => console.log(data))
.catch(err => console.log(err));

在上面的代码中,您可以看到 Amplify 帮助您完成的一些常见任务示例,例如使用电子邮件或短信进行多重身份验证 (MFA) 代码。目前支持的类别有

  • Auth:提供凭证自动化。开箱即用的实现使用 AWS 凭证进行签名,并使用来自 Amazon Cognito 的 OIDC JWT 令牌。支持常见功能,例如 MFA 功能。
  • Analytics:只需一行代码,即可在 Amazon Pinpoint 中获取已认证或未认证用户的跟踪数据。您可以根据需要将其扩展为自定义指标或属性。
  • API:提供与 RESTful API 的安全交互,利用 AWS Signature Version 4。API 模块在与 Amazon API Gateway 结合使用的无服务器基础设施上表现出色。
  • Storage:简化在 Amazon S3 中上传、下载和列出内容的命令。您还可以轻松地按用户将数据分组为公共或私人内容。
  • Caching:一个跨 Web 应用和 React Native 的 LRU 缓存接口,使用特定于实现的持久化。
  • i18n 和日志:提供国际化和本地化功能,以及调试和日志记录功能。

Amplify 的一个优点是它将“最佳实践”编码到您的特定编程环境设计中。例如,我们与客户和 React Native 开发者合作时发现,开发过程中为了快速实现功能而采取的捷径可能会在生产环境中带来问题。这可能会损害可扩展性或安全性,并强制进行基础设施重构和代码重构。

我们帮助开发者避免这种情况的一个例子是 基于 AWS Lambda 的无服务器参考架构。这些架构展示了在构建后端时如何结合使用 Amazon API Gateway 和 AWS Lambda 的最佳实践。这种模式被编码到 Amplify 的 API 类别中。您可以使用此模式与多个不同的 REST 端点交互,并将标头一直传递到您的 Lambda 函数以实现自定义业务逻辑。我们还发布了一个 AWS Mobile CLI,用于使用这些功能引导新的或现有 React Native 项目。要开始使用,只需通过 npm 安装,然后按照配置提示操作即可

npm install --global awsmobile-cli
awsmobile configure

另一个特定于移动生态系统的编码最佳实践示例是密码安全。默认的 Auth 类别实现利用 Amazon Cognito 用户池进行用户注册和登录。该服务实现了 安全远程密码协议,作为在身份验证尝试期间保护用户的一种方式。如果您倾向于阅读 协议的数学原理,您会注意到在原始根上计算密码验证器以生成组时,必须使用一个大素数。在 React Native 环境中,JIT 已禁用。这使得此类安全操作的 BigInteger 计算性能较低。为了解决这个问题,我们发布了 Android 和 iOS 中的原生桥接器,您可以将其链接到您的项目中

npm install --save aws-amplify-react-native
react-native link amazon-cognito-identity-js

我们也很高兴看到 Expo 团队已将此包含在其最新 SDK 中,这样您无需弹出即可使用 Amplify。

最后,特别是对于 React Native(和 React)开发,Amplify 包含高阶组件 (HOC),用于轻松封装功能,例如应用的注册和登录功能

import Amplify, { withAuthenticator } from 'aws-amplify-react-native';
import aws_exports from './aws-exports';

Amplify.configure(aws_exports);

class App extends React.Component {
...
}

export default withAuthenticator(App);

底层组件也作为 <Authenticator /> 提供,它使您能够完全控制自定义 UI。它还为您提供了一些用于管理用户状态的属性,例如他们是否已登录或正在等待 MFA 确认,以及在状态更改时可以触发的回调。

同样,您会找到可用于不同用例的通用 React 组件。您可以根据需要自定义这些组件,例如,在 Storage 模块中显示来自 Amazon S3 的所有私人图像

<S3Album
level="private"
path={path}
filter={(item) => /jpg/i.test(item.path)}/>

如前所述,您可以通过 props 控制许多组件功能,包括公共或私人存储选项。甚至还有在用户与某些 UI 组件交互时自动收集分析数据的功能

return <S3Album track/>

AWS Amplify 倾向于采用约定优于配置的开发风格,支持全局初始化或在类别级别进行初始化。最快的入门方法是使用 aws-exports 文件。但是,开发者也可以独立使用该库与现有资源。

如需深入了解其理念并观看完整演示,请查看来自 AWS re:Invent 的视频。

AWS AppSync

在 AWS Amplify 发布后不久,我们还发布了 AWS AppSync。这是一个具有离线和实时功能的完全托管的 GraphQL 服务。虽然您可以在不同的客户端编程语言(包括原生 Android 和 iOS)中使用 GraphQL,但它在 React Native 开发者中非常受欢迎。这是因为其数据模型与单向数据流和组件层次结构完美契合。

AWS AppSync 使您能够连接到自己 AWS 账户中的资源,这意味着您拥有并控制自己的数据。这是通过使用数据源来完成的,该服务支持 Amazon DynamoDBAmazon ElasticsearchAWS Lambda。这使您可以在单个 GraphQL API 中将功能(例如 NoSQL 和全文搜索)作为模式组合起来。这使您可以混合和匹配数据源。AppSync 服务还可以从模式配置,因此如果您不熟悉 AWS 服务,可以编写 GraphQL SDL,点击一个按钮,然后您就会自动启动并运行。

AWS AppSync 中的实时功能通过具有知名事件驱动模式的 GraphQL 订阅进行控制。由于 AWS AppSync 中的订阅通过 GraphQL 指令在模式上进行控制,并且一个模式可以使用任何数据源,这意味着您可以从使用 Amazon DynamoDB 和 Amazon Elasticsearch Service 的数据库操作,或者从使用 AWS Lambda 的基础设施的其他部分触发通知。

与 AWS Amplify 类似,您可以使用 AWS AppSync 为您的 GraphQL API 应用企业级安全功能。该服务让您可以使用 API 密钥快速入门。然而,当您投入生产时,它可以转换为使用 AWS Identity and Access Management (IAM) 或来自 Amazon Cognito 用户池的 OIDC 令牌。您可以通过类型上的策略在解析器级别控制访问。您甚至可以使用逻辑检查在运行时进行细粒度访问控制检查,例如检测用户是否是特定数据库资源的所有者。还有一些功能可以检查组员资格,以执行解析器或单个数据库记录访问。

为了帮助 React Native 开发者更多地了解这些技术,AWS AppSync 控制台主页上有一个内置的 GraphQL 示例模式供您启动。此示例会自动为您部署 GraphQL 模式、配置数据库表,并连接查询、变异和订阅。还有一个正常运行的 AWS AppSync 的 React Native 示例,它利用了这个内置模式(以及一个 React 示例),让您的客户端和云组件在几分钟内即可运行。

当您使用可插入 Apollo ClientAWSAppSyncClient 时,入门非常简单。AWSAppSyncClient 处理您的 GraphQL API 的安全性、签名、离线功能以及订阅握手和协商过程

import AWSAppSyncClient from "aws-appsync";
import { Rehydrated } from 'aws-appsync-react';
import { AUTH_TYPE } from "aws-appsync/lib/link/auth-link";

const client = new AWSAppSyncClient({
url: awsconfig.graphqlEndpoint,
region: awsconfig.region,
auth: {type: AUTH_TYPE.API_KEY, apiKey: awsconfig.apiKey}
});

AppSync 控制台提供可下载的配置文件,其中包含您的 GraphQL 端点、AWS 区域和 API 密钥。然后您可以将客户端与 React Apollo 结合使用

const WithProvider = () => (
<ApolloProvider client={client}>
<Rehydrated>
<App />
</Rehydrated>
</ApolloProvider>
);

此时,您可以使用标准的 GraphQL 查询

query ListEvents {
listEvents{
items{
__typename
id
name
where
when
description
comments{
__typename
items{
__typename
eventId
commentId
content
createdAt
}
nextToken
}
}
}
}

上述示例展示了一个使用 AppSync 提供的示例应用模式的查询。它不仅展示了与 DynamoDB 的交互,还包括数据分页(包括加密令牌)以及 EventsComments 之间的类型关系。由于应用已配置 AWSAppSyncClient,数据会自动离线持久化,并在设备重新连接时同步。

您可以在此视频中深入了解其背后的客户端技术和 React Native 演示

反馈

库背后的团队渴望了解这些库和服务对您的使用情况。他们也想知道我们还能做些什么,以使您使用云服务进行 React 和 React Native 开发变得更容易。请在 GitHub 上联系 AWS 移动团队,获取有关 AWS AmplifyAWS AppSync 的信息。

在 React Native 中实现 Twitter 的应用加载动画

·阅读 12 分钟
Eli White
Eli White
Meta 软件工程师

Twitter 的 iOS 应用有一个我非常喜欢的加载动画。

一旦应用准备就绪,Twitter 标志便会愉快地展开,显示出应用。

我想弄清楚如何使用 React Native 重现这个加载动画。


为了理解如何构建它,我首先需要理解加载动画的不同部分。了解其精妙之处的最简单方法是放慢速度。

其中有几个主要部分我们需要弄清楚如何构建。

  1. 缩放小鸟。
  2. 随着小鸟的增长,显示出底部的应用
  3. 最后稍微缩小应用

我花了很长时间才弄清楚如何制作这个动画。

我最初有一个错误的假设,认为蓝色背景和 Twitter 小鸟是位于应用之上的一层,并且随着小鸟的增长,它会变得透明,从而显示出底部的应用。这种方法行不通,因为 Twitter 小鸟变得透明会显示蓝色层,而不是底部的应用!

幸运的是,亲爱的读者,您不必经历我同样的挫败。您将获得这个直接进入重点的精彩教程!


正确方法

在我们开始编写代码之前,了解如何分解它很重要。为了帮助可视化此效果,我在 CodePen 中重新创建了它(嵌入在几个段落中),以便您可以交互式地查看不同的图层。

这种效果主要有三个图层。第一个是蓝色背景层。尽管它看起来出现在应用顶部,但实际上它在后面。

然后我们有一个纯白色层。最后,在最前面,是我们的应用。


这个动画的主要技巧是使用 Twitter 标志作为遮罩,同时遮罩应用和白色层。我不会深入遮罩的细节,网上有大量资源可供参考

在此上下文中,遮罩的基本原理是:遮罩的不透明像素显示它们所遮罩的内容,而遮罩的透明像素则隐藏它们所遮罩的内容。

我们使用 Twitter 标志作为遮罩,并让它遮罩两个图层:纯白色层和应用层。

为了显示应用,我们放大遮罩,直到它大于整个屏幕。

当遮罩放大时,我们淡入应用层的 opacity,显示应用并隐藏其后面的纯白色层。为了完成效果,我们将应用层从大于 1 的比例开始,并在动画结束时将其缩小到 1。然后我们隐藏非应用层,因为它们将不再被看到。

有人说一张图片胜过千言万语。那么一个交互式可视化又值多少言语呢?点击“下一步”按钮来浏览动画。显示图层可以为您提供侧视图。网格在那里是为了帮助可视化透明图层。

现在,关于 React Native

好的。现在我们知道了要构建什么以及动画的工作原理,我们可以开始编写代码了——这才是您来这里的真正原因。

这个难题的主要部分是 MaskedViewIOS,一个核心的 React Native 组件。

import {MaskedViewIOS} from 'react-native';

<MaskedViewIOS maskElement={<Text>Basic Mask</Text>}>
<View style={{backgroundColor: 'blue'}} />
</MaskedViewIOS>;

MaskedViewIOS 接受 maskElementchildren 属性。子元素由 maskElement 进行遮罩。请注意,遮罩不必是图像,它可以是任何任意视图。上面示例的行为是渲染蓝色视图,但它只在 maskElement 中的“Basic Mask”文字所在的位置可见。我们刚刚制作了复杂的蓝色文本。

我们想要做的是渲染我们的蓝色层,然后在上面渲染带有 Twitter 标志的遮罩应用层和白色层。

{
fullScreenBlueLayer;
}
<MaskedViewIOS
style={{flex: 1}}
maskElement={
<View style={styles.centeredFullScreen}>
<Image source={twitterLogo} />
</View>
}>
{fullScreenWhiteLayer}
<View style={{flex: 1}}>
<MyApp />
</View>
</MaskedViewIOS>;

这将为我们提供下方看到的图层。

现在是动画部分

我们已经具备了使此动画工作所需的所有部件,下一步是使它们动起来。为了使这个动画感觉良好,我们将利用 React Native 的 Animated API。

Animated 允许我们在 JavaScript 中声明性地定义动画。默认情况下,这些动画在 JavaScript 中运行,并告诉原生层每帧要进行的更改。尽管 JavaScript 会尝试每帧更新动画,但它可能无法足够快地完成,从而导致掉帧(卡顿)发生。这不是我们想要的!

Animated 有一个特殊行为,允许您在没有卡顿的情况下获得动画。Animated 有一个名为 useNativeDriver 的标志,它在动画开始时将您的动画定义从 JavaScript 发送到原生层,允许原生端处理动画更新,而无需每帧都往返于 JavaScript。useNativeDriver 的缺点是您只能更新特定的一组属性,主要是 transformopacity。您不能使用 useNativeDriver 动画背景颜色之类的东西,至少目前不行——我们将来会添加更多,当然您也可以随时为您项目所需的属性提交 PR,造福整个社区 😀。

由于我们希望这个动画流畅,我们将在这些限制内工作。要更深入地了解 useNativeDriver 的内部工作原理,请查看我们宣布它的博客文章

分解我们的动画

我们的动画有 4 个组成部分

  1. 放大小鸟,显示应用和纯白色层
  2. 淡入应用
  3. 缩小应用
  4. 完成后隐藏白色层和蓝色层

使用 Animated,有两种主要方式来定义动画。第一种是使用 Animated.timing,它允许您精确指定动画的运行时长,以及一个缓动曲线来平滑运动。另一种方法是使用基于物理的 API,例如 Animated.spring。使用 Animated.spring,您可以指定参数,例如弹簧中的摩擦力和张力,然后让物理引擎运行您的动画。

我们有多个动画希望同时运行,它们都密切相关。例如,我们希望应用在遮罩正在显示的过程中开始淡入。由于这些动画密切相关,我们将使用带有单个 Animated.ValueAnimated.timing

Animated.Value 是一个原生值的封装,Animated 使用它来了解动画的状态。通常,对于一个完整的动画,您只希望有一个这样的值。大多数使用 Animated 的组件会将该值存储在 state 中。

由于我将此动画视为在完整动画的不同时间点发生的步骤,因此我们将 Animated.Value 从 0 开始,表示完成 0%,并以 100 结束,表示完成 100%。

我们的初始组件状态将如下所示。

state = {
loadingProgress: new Animated.Value(0),
};

当我们准备开始动画时,我们告诉 Animated 将此值动画到 100。

Animated.timing(this.state.loadingProgress, {
toValue: 100,
duration: 1000,
useNativeDriver: true, // This is important!
}).start();

然后我尝试粗略估计动画的不同部分以及它们在整个动画不同阶段应具有的值。下面是一个表格,列出了动画的不同部分以及我认为它们在时间推移过程中不同点应具有的值。

Twitter 小鸟遮罩应该从比例 1 开始,在尺寸飙升之前会先变小。因此,在动画进行到 10% 时,它应该具有 0.8 的比例值,然后最终飙升到比例 70。坦率地说,选择 70 是相当随意的,它需要足够大以使小鸟完全显示屏幕,而 60 则不够大 😀。不过,这一部分有趣的是,数字越大,它看起来增长得越快,因为它必须在相同的时间内达到目标。这个数字经过了一些反复试验才使其与此标志看起来不错。不同尺寸的标志/设备将需要不同的最终比例,以确保整个屏幕都被显示。

应用应该保持不透明一段时间,至少在 Twitter 标志变小期间。根据官方动画,我希望在小鸟放大到一半时开始显示它,并很快完全显示出来。因此,在动画进行到 15% 时我们开始显示它,在整个动画进行到 30% 时它完全可见。

应用比例从 1.1 开始,并在动画结束时缩小到其常规比例。

现在,用代码实现。

我们上面所做的实质上是将动画进度百分比的值映射到各个部分的对应值。我们使用 Animated 的 .interpolate 方法来完成。我们创建了 3 个不同的样式对象,每个动画部分一个,使用基于 this.state.loadingProgress 的插值。

const loadingProgress = this.state.loadingProgress;

const opacityClearToVisible = {
opacity: loadingProgress.interpolate({
inputRange: [0, 15, 30],
outputRange: [0, 0, 1],
extrapolate: 'clamp',
// clamp means when the input is 30-100, output should stay at 1
}),
};

const imageScale = {
transform: [
{
scale: loadingProgress.interpolate({
inputRange: [0, 10, 100],
outputRange: [1, 0.8, 70],
}),
},
],
};

const appScale = {
transform: [
{
scale: loadingProgress.interpolate({
inputRange: [0, 100],
outputRange: [1.1, 1],
}),
},
],
};

现在我们有了这些样式对象,我们可以在渲染本文前面提到的视图片段时使用它们。请注意,只有 Animated.ViewAnimated.TextAnimated.Image 能够使用包含 Animated.Value 的样式对象。

const fullScreenBlueLayer = (
<View style={styles.fullScreenBlueLayer} />
);
const fullScreenWhiteLayer = (
<View style={styles.fullScreenWhiteLayer} />
);

return (
<View style={styles.fullScreen}>
{fullScreenBlueLayer}
<MaskedViewIOS
style={{flex: 1}}
maskElement={
<View style={styles.centeredFullScreen}>
<Animated.Image
style={[styles.maskImageStyle, imageScale]}
source={twitterLogo}
/>
</View>
}>
{fullScreenWhiteLayer}
<Animated.View
style={[opacityClearToVisible, appScale, {flex: 1}]}>
{this.props.children}
</Animated.View>
</MaskedViewIOS>
</View>
);

耶!现在我们的动画部分看起来如我们所愿了。现在我们只需清理蓝色和白色层,它们将不再被看到。

要知道何时可以清理它们,我们需要知道动画何时完成。幸运的是,我们调用的 Animated.timing.start 方法接受一个可选的回调函数,该函数在动画完成时运行。

Animated.timing(this.state.loadingProgress, {
toValue: 100,
duration: 1000,
useNativeDriver: true,
}).start(() => {
this.setState({
animationDone: true,
});
});

现在我们的 state 中有一个值可以知道动画是否完成,我们可以修改我们的蓝色和白色层来使用它。

const fullScreenBlueLayer = this.state.animationDone ? null : (
<View style={[styles.fullScreenBlueLayer]} />
);
const fullScreenWhiteLayer = this.state.animationDone ? null : (
<View style={[styles.fullScreenWhiteLayer]} />
);

瞧!我们的动画现在可以工作了,一旦动画完成,我们就会清理掉未使用的图层。我们已经构建了 Twitter 应用的加载动画!

等等,我的不工作!

亲爱的读者,请不要担心。我也讨厌那些只提供部分代码而不提供完整源代码的指南。

该组件已发布到 npm,并在 GitHub 上以 react-native-mask-loader 的形式提供。要在您的手机上试用,它可在 Expo 上使用

更多阅读/额外内容

  1. 阅读 React Native 文档后,这本 gitbook 是学习 Animated 的极佳资源。
  2. 实际的 Twitter 动画似乎在最后加快了遮罩的显示速度。尝试修改加载器,使用不同的缓动函数(或弹簧!)以更好地匹配该行为。
  3. 当前遮罩的最终比例是硬编码的,可能无法在平板电脑上完全显示整个应用。根据屏幕尺寸和图像尺寸计算最终比例将是一个很棒的 PR。

React Native 月报 #6

·阅读 4 分钟
Tomislav Tenodi
Speck 创始人

React Native 月度会议仍在顺利进行!请务必查看本文底部的说明以了解下一次会议。

Expo

  • 祝贺 Devin AbbottHoussein Djirdeh 预发布了“全栈 React Native”一书!它通过构建几个小型应用来引导您学习 React Native。
  • 发布了第一个(实验性)版本的 reason-react-native-scripts,以帮助人们轻松尝试 ReasonML
  • Expo SDK 24 已发布!它使用 React Native 0.51,并包含一堆新功能和改进:独立应用中的图像捆绑(无需首次加载时缓存!)、图像处理 API(裁剪、调整大小、旋转、翻转)、人脸识别 API、新的发布渠道功能(为给定渠道设置活动版本并回滚)、用于跟踪独立应用构建的 Web 控制面板,以及修复了 OpenGL Android 实现和 Android 多任务处理器的长期存在错误,这只是其中的一小部分。
  • 从今年一月开始,我们正在为 React Navigation 分配更多资源。我们坚信仅使用 React 组件和像 Animated 和 react-native-gesture-handler 这样的基本元素来构建 React Native 导航是可能且值得的,我们对计划中的一些改进感到非常兴奋。如果您希望为社区做贡献,请查看 react-native-mapsreact-native-svg,它们都需要一些帮助!

Infinite Red

Microsoft

  • 已启动一个拉取请求,旨在将核心 React Native Windows 桥接到 .NET Standard,使其有效实现操作系统无关性。希望许多其他 .NET Core 平台能够通过自己的线程模型、JavaScript 运行时和 UIManagers(例如 JavaScriptCore、Xamarin.Mac、Linux Gtk# 和 Samsung Tizen 选项)来扩展该桥接。

Wix

  • Detox
    • 为了使我们能够扩展 E2E 测试,我们希望最大程度地减少在 CI 上花费的时间,我们正在为 Detox 开发并行化支持。
    • 提交了一个拉取请求,以启用对自定义 flavor 构建的支持,从而更好地支持 E2E 中的模拟。
  • DetoxInstruments
    • 开发 DetoxInstruments 的杀手级功能被证明是一项非常具有挑战性的任务,在任何给定时间获取 JavaScript 回溯需要自定义 JSCore 实现以支持 JS 线程挂起。在 Wix 应用内部测试分析器揭示了关于 JS 线程的有趣见解。
    • 该项目目前尚不稳定,无法广泛使用,但正在积极开发中,我们希望很快公布。
  • React Native Navigation
    • V2 的开发速度已大幅提升,直到现在,我们只有 1 名开发者投入 20% 的时间,而现在我们有 3 名开发者全职投入!
  • Android 性能
    • 用最新版本(webkitGTK 项目的尖端,带有自定义 JIT 配置)替换 RN 中捆绑的旧 JSCore,使 JS 线程的性能提高了 40%。下一步是编译其 64 位版本。这项工作基于 Android 的 JSC 构建脚本。在此处关注其当前状态

下次会议

有一些讨论关于重新定位这次会议,以讨论一个单一而具体的主题(例如导航、将 React Native 模块移入单独的仓库、文档等)。我们认为这样可以为 React Native 社区做出最好的贡献。这可能在下一次会议中进行。请随时推特您希望涵盖的主题。

React Native 月报 #5

·阅读 4 分钟
Tomislav Tenodi
Speck 创始人

React Native 月度会议仍在继续!让我们看看我们的团队都在忙些什么。

Callstack

  • 我们一直在致力于 React Native CI。最重要的是,我们已从 Travis 迁移到 Circle,使 React Native 拥有一个单一、统一的 CI 流水线。
  • 我们组织了黑客十月节 - React Native 版,在那里我们与参与者一起尝试向开源项目提交了许多拉取请求。
  • 我们持续开发 Haul。上个月,我们发布了两个新版本,包括 webpack 3 支持。我们计划添加 CRNAExpo 支持,并致力于改进 HMR。我们的路线图在问题跟踪器上公开。如果您想提出改进建议或提供反馈,请告诉我们!

Expo

  • 发布了 Expo SDK 22(使用 React Native 0.49)并为其更新了 CRNA
    • 包括改进的启动画面 API、基本的 ARKit 支持、“DeviceMotion” API、iOS11 上的 SFAuthenticationSession 支持以及更多功能
  • 您的 snacks 现在可以包含多个 JavaScript 文件,您只需将图像和其他资产拖入编辑器即可上传。
  • 贡献给 react-navigation 以添加对 iPhone X 的支持。
  • 在使用 Expo 构建大型应用程序时,我们将重点关注粗糙之处。例如
    • 对部署到多个环境提供一流支持:预生产、生产和任意渠道。渠道将支持回滚和为给定渠道设置活动版本。如果您想成为早期测试者,请告诉我们,@expo_io
    • 我们还在努力改进我们的独立应用构建基础设施,并增加对独立应用构建中图像和其他非代码资产的捆绑支持,同时保留通过空中更新资产的能力。

Facebook

  • 更好的 RTL 支持
    • 我们正在引入许多方向感知的样式。
      • 位置
        • (左|右) → (开始|结束)
      • 外边距
        • 外边距(左|右) → 外边距(开始|结束)
      • 内边距
        • 内边距(左|右) → 内边距(开始|结束)
      • 边框
        • 顶部边框(左|右)半径 → 顶部边框(开始|结束)半径
        • 底部边框(左|右)半径 → 底部边框(开始|结束)半径
        • 边框(左|右)宽度 → 边框(开始|结束)宽度
        • 边框(左|右)颜色 → 边框(开始|结束)颜色
    • 在 RTL 中,位置、外边距、内边距和边框样式的“左”和“右”的含义被交换了。在几个月内,我们将取消这种行为,使“左”始终表示“左”,“右”始终表示“右”。这些破坏性更改隐藏在一个标志下。在您的 React Native 组件中使用 I18nManager.swapLeftAndRightInRTL(false) 来选择启用它们。
  • 正在致力于对我们内部的原生模块进行 Flow 类型检查,并利用这些类型在 Java 中生成接口,在 ObjC 中生成协议,这些是原生实现必须实现的。我们希望这个代码生成器最早能在明年开源。

Infinite Red

  • 用于帮助 React Native 及其他项目的新开源工具。更多信息请见此处
  • 正在改造 Ignite,以发布新的样板(代号:Bowser)。

Shoutem

  • 正在改进 Shoutem 上的开发流程。我们希望简化从创建应用到第一个自定义屏幕的过程,使其非常简单,从而降低新 React Native 开发者的门槛。准备了一些工作坊来测试新功能。我们还改进了 Shoutem CLI 以支持新的流程。
  • Shoutem UI 收到了一些组件改进和 bug 修复。我们还检查了与最新 React Native 版本的兼容性。
  • Shoutem 平台收到了一些值得注意的更新,新的集成作为 开源扩展项目的一部分提供。我们很高兴看到其他开发者对 Shoutem 扩展的积极开发。我们积极联系并提供关于其扩展的建议和指导。

下次会议

下次会议定于 2017 年 12 月 6 日星期三举行。如果您对我们如何改进会议成果有任何建议,请随时在 Twitter 上联系我。

React Native 月报 #4

·阅读 3 分钟
Mike Grabowski
Mike Grabowski
Callstack 首席技术官兼联合创始人

React Native 月度会议仍在继续!以下是各团队的会议纪要

Callstack

  • React Native EU 已结束。来自 33 个国家的 300 多名参与者访问了弗罗茨瓦夫。演讲内容可在 YouTube 上找到。
  • 会议结束后,我们正在慢慢恢复开源工作计划。值得一提的是,我们正在开发 react-native-opentok 的下一个版本,该版本修复了大多数现有问题。

GeekyAnts

正在尝试通过以下方式降低 React Native 开发者的入门门槛

  • React Native EU 上宣布了 BuilderX.io。BuilderX 是一个设计工具,可直接处理 JavaScript 文件(目前仅支持 React Native),以生成美观、可读且可编辑的代码。
  • 推出了 ReactNativeSeed.com,它为您的下一个 React Native 项目提供了一套样板。它提供了多种选项,包括用于数据类型的 TypeScript & Flow、用于状态管理的 MobX、Redux 和 mobx-state-tree,以及 CRNA 和纯 React-Native 作为技术栈。

Expo

  • 将很快发布 SDK 21,它将添加对 react-native 0.48.3 的支持,以及 Expo SDK 中的一系列 bug 修复/可靠性改进/新功能,包括视频录制、新的启动画面 API、对 react-native-gesture-handler 的支持,以及改进的错误处理。
  • 关于 react-native-gesture-handlerSoftware MansionKrzysztof Magiera 仍在继续推进,我们一直在帮助他进行测试并资助其部分开发时间。将其集成到 Expo SDK21 中将使人们能够在 Snack 中轻松试用,因此我们很期待看到大家会创造出什么。
  • 关于改进的错误日志记录/处理——有关日志记录的详细信息(特别是“问题 2”),请参阅此 Expo 内部 PR 的要点;有关处理导入 npm 标准库模块失败尝试的更改,请参阅此提交。通过这种方式,React Native 上游有大量机会可以改进错误消息,我们将继续进行后续的上游 PR。社区也能参与进来将非常棒。
  • native.directory 持续增长,您可以从 GitHub 仓库添加您的项目。
  • 访问北美各地的黑客马拉松,包括 PennAppsHack The NorthHackMIT,以及即将到来的 MHacks

Facebook

  • 正在致力于改进 Android 上的 <Text><TextInput> 组件。(<TextInput> 的原生自动增长;深层嵌套的 <Text> 组件布局问题;更好的代码结构;性能优化)。
  • 我们仍在寻找愿意帮助分类处理问题和拉取请求的额外贡献者。

Microsoft

  • 发布了 CodePush 的代码签名功能。React Native 开发者现在可以在 CodePush 中签署他们的应用捆绑包。公告可在此处找到
  • 正在努力完成 CodePush 与 Mobile Center 的集成。同时也在考虑测试/崩溃集成。

下次会议

下次会议定于 2017 年 10 月 10 日星期三举行。由于这只是我们的第四次会议,我们想知道这些会议纪要对 React Native 社区有何益处。如果您对我们如何改进会议成果有任何建议,请随时在 Twitter 上联系我。

React Native 月报 #3

·阅读 5 分钟
Mike Grabowski
Mike Grabowski
Callstack 首席技术官兼联合创始人

React Native 月度会议仍在继续!本月的会议略短,因为我们的大部分团队都在忙于发布。下个月,我们将在波兰弗罗茨瓦夫参加 React Native EU 大会。请务必购票并亲自前往!与此同时,让我们看看我们的团队都在忙些什么。

团队

在第三次会议上,有 5 个团队加入我们

笔记

以下是各团队的会议纪要。

Callstack

  • 最近开源了 react-native-material-palette。它从图像中提取主要颜色,帮助您创建视觉吸引力强的应用。目前仅支持 Android,但我们正在考虑未来增加对 iOS 的支持。
  • 我们已将 HMR 支持引入 haul 和其他许多很棒的功能!请查看最新版本。
  • React Native EU 2017 即将到来!下个月将全部围绕 React Native 和波兰展开!请务必抓住最后的机会购票,点此

Expo

  • 发布了在 Snack 上安装 npm 包的支持。通常的 Expo 限制适用——包不能依赖于 Expo 中尚未包含的自定义原生 API。我们还在努力支持 Snack 中的多个文件和资产上传。Satyajit 将在 React Native Europe 谈论 Snack。
  • 发布了 SDK20,支持摄像头、支付、安全存储、磁力计、暂停/恢复文件系统下载,以及改进的启动/加载屏幕。
  • 继续与 Krzysztof 合作开发 react-native-gesture-handler。请试用一下,使用 PanResponder 或原生手势识别器重建您以前构建的一些手势,并告诉我们您遇到的问题。
  • 正在试验 JSC 调试协议,并处理 Canny 上的一系列功能请求。

Facebook

  • 上个月我们讨论了 GitHub 问题跟踪器的管理,并表示我们将尝试改进以解决项目的可维护性问题。
  • 目前,未解决问题的数量稳定在 600 个左右,并且似乎会保持一段时间。在过去的一个月里,我们因缺乏活动(定义为过去 60 天内没有评论)而关闭了 690 个问题。在这 690 个问题中,有 58 个因各种原因被重新打开(维护者承诺提供修复,或者贡献者提出了一个很好的理由来保持问题开放)。
  • 在可预见的未来,我们计划继续自动关闭过时问题。我们希望达到这样的状态:跟踪器中打开的每一个有影响力的问题都能得到处理,但我们尚未实现。我们需要维护者的全力帮助来分类处理问题,并确保我们不会遗漏引入回归或破坏性更改的问题,特别是那些影响新创建项目的问题。有兴趣提供帮助的人可以使用 Facebook GitHub Bot 来分类处理问题和拉取请求。新的维护者指南包含更多关于分类处理和使用 GitHub Bot 的信息。请将自己添加到问题工作组,并鼓励其他活跃的社区成员也这样做!

Microsoft

  • 新的 Skype 应用是基于 React Native 构建的,旨在促进尽可能多的代码在平台之间共享。基于 React Native 的 Skype 应用目前可在 Android 和 iOS 应用商店中下载。
  • 在使用 React Native 构建 Skype 应用时,我们会向 React Native 提交拉取请求,以解决我们遇到的 bug 和缺失的功能。到目前为止,我们已经有大约 70 个拉取请求被合并
  • React Native 使我们能够从同一代码库支持 Android 和 iOS Skype 应用。我们还希望使用该代码库来支持 Skype Web 应用。为了帮助我们实现这一目标,我们构建并开源了一个基于 React/React Native 的薄层,名为 ReactXP。ReactXP 提供了一组跨平台组件,在针对 iOS/Android 时映射到 React Native,在针对 Web 时映射到 react-dom。ReactXP 的目标与另一个名为 React Native for Web 的开源库相似。ReactXP 常见问题解答中简要描述了这些库的方法有何不同。

Shoutem

  • 我们正在继续努力改进和简化使用 Shoutem 构建应用时的开发者体验。
  • 开始将我们所有的应用迁移到 react-navigation,但我们最终推迟了这项工作,直到发布更稳定的版本,或者其中一个原生导航解决方案变得稳定。
  • 正在将我们所有的扩展和大部分开源库(animationthemeui)更新到 React Native 0.47.1。

下次会议

下次会议定于 2017 年 9 月 13 日星期三举行。由于这只是我们的第三次会议,我们想知道这些会议纪要对 React Native 社区有何益处。如果您对我们如何改进会议成果有任何建议,请随时在 Twitter 上联系我。

Marketplace 中的 React Native 性能

·阅读 6 分钟
Facebook 软件工程师

React Native 在 Facebook 家族的多个应用中的多个地方使用,包括主要 Facebook 应用中的顶级选项卡。本文的重点是一个高度可见的产品,Marketplace。它在十几个国家/地区可用,使用户能够发现其他用户提供的产品和服务。

在 2017 年上半年,通过 Relay 团队、Marketplace 团队、移动 JS 平台团队和 React Native 团队的共同努力,我们将 Android 2010-11 年级设备的 Marketplace 交互时间 (TTI) 缩短了一半。Facebook 历来将这些设备视为低端 Android 设备,它们在任何平台或设备类型上都具有最慢的 TTI。

一个典型的 React Native 启动过程如下所示

免责声明:比例不具代表性,会根据 React Native 的配置和使用方式而有所不同。

我们首先初始化 React Native 核心(又称“桥接”),然后运行产品特定的 JavaScript,它决定了 React Native 将在原生处理时间中渲染哪些原生视图。

另一种方法

我们早期犯的一个错误是让 Systrace 和 CTScan 来主导我们的性能优化工作。这些工具在 2016 年帮助我们发现了很多唾手可得的成果,但我们发现 Systrace 和 CTScan 都无法代表生产环境场景,也无法模拟实际情况。在细分项中花费的时间比例通常不正确,有时甚至严重偏离实际。极端情况下,我们预期只需几毫秒的事情,实际上却需要数百甚至数千毫秒。尽管如此,CTScan 仍然很有用,我们发现它能在三分之一的回归问题投入生产环境之前捕获它们。

在 Android 上,我们将这些工具的缺点归因于以下事实:1) React Native 是一个多线程框架,2) Marketplace 与新闻动态及其他顶级选项卡等大量复杂视图并存,3) 计算时间差异很大。因此,本学期我们几乎所有决策和优先级都由生产环境测量和细分数据来驱动。

生产环境检测之路

对生产环境进行检测表面上听起来很简单,但结果却是一个相当复杂的过程。它需要多个迭代周期,每个周期 2-3 周;这是因为从将提交合并到主分支,到将应用推送到 Play 商店,再到收集足够的生产样本以确保我们工作的准确性,都存在延迟。每个迭代周期都涉及到发现我们的细分是否准确,它们是否具有正确的粒度级别,以及它们是否正确地加起来等于总时间。我们不能依赖 alpha 和 beta 版本,因为它们不代表普通用户。实质上,我们非常细致地基于数百万样本的聚合数据,构建了一个非常准确的生产环境追踪。

我们仔细验证了细分中每一毫秒都正确加起来等于其父级指标的原因之一是,我们很早就意识到我们的检测存在缺陷。结果发现,我们最初的细分没有考虑线程跳转导致的停顿。线程跳转本身并不昂贵,但跳转到正在忙碌的线程却非常昂贵。我们最终通过在适当的时机插入 Thread.sleep() 调用,在本地重现了这些阻塞,并通过以下方式成功修复了它们:

  1. 移除对 AsyncTask 的依赖,
  2. 取消在 UI 线程上强制初始化 ReactContext 和 NativeModules,以及
  3. 移除对在初始化时测量 ReactRootView 的依赖。

总的来说,解决这些线程阻塞问题使启动时间减少了 25% 以上。

生产环境指标也挑战了我们之前的一些假设。例如,我们过去常常在启动路径上预加载许多 JavaScript 模块,假设将模块放在一个 bundle 中可以降低它们的初始化成本。然而,预加载和共置这些模块的成本远远超过了收益。通过重新配置我们的内联 require 黑名单并从启动路径中移除 JavaScript 模块,我们得以避免加载不必要的模块,例如 Relay Classic(当只需要 Relay Modern 时)。如今,我们的 RUN_JS_BUNDLE 细分速度提升了 75% 以上。

我们还通过研究特定于产品的原生模块获得了成功。例如,通过惰性注入原生模块的依赖项,我们将该原生模块的成本降低了 98%。通过消除 Marketplace 启动与其他产品的竞争,我们以同等幅度缩短了启动时间。

最棒的是,这些改进中有许多都广泛适用于所有使用 React Native 构建的屏幕。

结论

人们通常认为 React Native 的启动性能问题是由于 JavaScript 运行缓慢或网络时间过长造成的。虽然加快 JavaScript 等方面的速度会显著降低 TTI(可交互时间),但这些因素对 TTI 的贡献百分比远低于之前所认为的。

到目前为止的教训是:测量,测量,再测量! 一些成功来自于将运行时成本转移到构建时,例如 Relay Modern 和 Lazy NativeModules。其他成功来自于更智能地并行化代码或移除无用代码来避免不必要的工作。还有一些成功来自于 React Native 的重大架构更改,例如清理线程阻塞。性能没有一劳永逸的解决方案,长期的性能提升将来自于渐进式的检测和改进。不要让认知偏见影响你的决策。相反,要仔细收集和解释生产数据,以指导未来的工作。

未来计划

从长远来看,我们希望 Marketplace 的 TTI(可交互时间)能够与使用原生技术构建的类似产品相媲美,并且总的来说,让 React Native 的性能与原生性能持平。此外,尽管本学期我们大幅降低了桥接启动成本约 80%,但我们计划通过 Prepack 等项目以及更多的构建时处理,将 React Native 桥接的成本降至接近零。

React Native 月报 #2

·阅读时长 9 分钟
Tomislav Tenodi
Shoutem 产品经理

React Native 月度会议继续进行!本次会议,我们有幸邀请到 Infinite Red 加入,他们是 Chain React,React Native 大会背后的杰出团队。由于在座的大多数人都将在 Chain React 大会上发表演讲,我们将会议推迟了一周。大会的演讲视频已经发布到线上,我鼓励大家观看。那么,让我们看看各个团队都在忙些什么吧。

团队

第二次会议共有 9 个团队参加

笔记

以下是各团队的会议纪要。

爱彼迎

Callstack

  • Mike Grabowski 一如既往地负责 React Native 的月度发布,包括推出了一些 beta 版本。特别是,他们正在努力将 v0.43.5 版本发布到 npm,因为它能解除 Windows 用户的阻塞!
  • Haul 方面的工作进展缓慢但持续。目前有一个添加 HMR 的拉取请求,其他改进也已发布。最近有一些行业领导者开始采用它。可能计划在该领域启动一份全职带薪工作。
  • 来自 Jest 团队的 Michał Pierzchała 本月加入了 Callstack。他将协助维护 Haul,并可能参与 Metro BundlerJest 的工作。
  • Satyajit Sahoo 现在和我们在一起了,太棒了!
  • 我们的开源部门即将推出许多很棒的东西。特别是,我们正在努力将 Material Palette API 引入 React Native。计划最终发布我们的原生 iOS 工具包,旨在提供与原生组件 1:1 的外观和感觉。

Expo

  • 最近推出了 Native Directory,以帮助发现和评估 React Native 生态系统中的库。问题在于:库太多,难以测试,需要手动应用启发式方法,并且不容易立即知道哪些是您应该使用的最佳库。也很难知道某些东西是否与 CRNA/Expo 兼容。因此 Native Directory 试图解决这些问题。请查看它并将您的库添加进去。库列表在此处。这只是我们的首次尝试,我们希望它由社区拥有和运行,而不仅仅是 Expo 团队。因此,如果您认为这有价值并希望使其更好,请加入!
  • 通过 Expo SDK 19,我们已在 Snack 中初步支持安装 npm 包。如果您在使用过程中遇到任何问题,请告知我们,我们仍在解决一些 bug。与 Native Directory 一起,这将使测试仅具有 JS 依赖项或包含在 Expo SDK 中的库变得容易。请尝试一下:
  • 我们发布了 Expo SDK19,其中包含全面的改进,我们现在正在使用更新的 Android JSC
  • 正在与 Alexander Kotliarskyi 一起编写文档中的指南,其中包含有关如何改进应用用户体验的技巧列表。请加入我们,添加内容到列表中或协助编写其中一部分!
  • 继续致力于:音频/视频、摄像头、手势(与 Software Mansion 合作,react-native-gesture-handler)、GL 摄像头集成,并希望在 SDK20(8 月份)首次推出其中一些功能,届时其他功能也将有显著改进。我们才刚开始在 Expo 客户端中构建用于后台工作(地理定位、音频、通知处理等)的基础设施。
  • Adam Miskiewiczreact-navigation 中模仿 UINavigationController 的过渡效果取得了不错的进展。请查看他的推文中的早期版本——即将发布。也请查看他上游提交MaskedViewIOS。如果你有能力和意愿为 Android 实现 MaskedView,那将非常棒!

Facebook

  • Facebook 正在内部探索将原生 ComponentKitLitho 组件嵌入到 React Native 中的可能性。
  • 非常欢迎大家为 React Native 做出贡献!如果您想知道如何贡献,《如何贡献》指南描述了我们的开发流程并列出了发送您的第一个拉取请求的步骤。还有其他不需编写代码的贡献方式,例如分类问题或更新文档。
    • 截至撰写本文时,React Native 有 635未解决问题249未处理拉取请求。这让我们的维护者不堪重负,而且当内部修复问题时,很难确保相关任务得到更新。
    • 我们不确定在保持社区满意度的同时处理此问题的最佳方法是什么。一些(但不是全部!)选项包括关闭过时问题、给予更多人管理问题的权限,以及自动关闭不遵循问题模板的问题。我们编写了《对维护者的期望》指南,以设定期望并避免意外。如果您对我们如何改善维护者的体验,并确保提出问题和拉取请求的人感受到被倾听和重视有任何想法,请告诉我们!

GeekyAnts

  • 我们在 Chain React 大会上演示了与 React Native 文件配合使用的 Designer Tool。许多与会者都报名了等候名单。
  • 我们还在研究其他跨平台解决方案,例如 Google Flutter(一项重大比较正在进行中)、Kotlin NativeApache Weex,以了解它们的架构差异以及我们可以从中学到什么来提高 React Native 的整体性能。
  • 我们的大部分应用已切换到 react-navigation,这提高了整体性能。
  • 此外,还宣布了 NativeBase Market——一个适用于 React Native 组件和应用的开发人员专属市场。

Infinite Red

Microsoft

  • CodePush 现已集成到 Mobile Center 中。现有用户的工作流程不会发生变化。
    • 一些人报告了重复应用的问题——他们已经在 Mobile Center 上有一个应用。我们正在努力解决这些问题,但如果您有两个应用,请告诉我们,我们可以为您合并它们。
  • Mobile Center 现在支持 CodePush 的推送通知。我们还展示了如何将通知和 CodePush 结合起来用于 A/B 测试应用——这是 React Native 架构所独有的。
  • VS Code 在 React Native 调试方面有一个已知问题——几天后的下一个扩展版本将修复此问题。
  • 由于微软内部还有许多其他团队也在开发 React Native,我们将在下次会议上努力争取所有团队的更好代表。

Shoutem

  • 我们完成了在 Shoutem 上简化 React Native 开发的过程。在 Shoutem 上开发应用时,您可以使用所有标准的 react-native 命令。
  • 我们做了大量工作,试图找出在 React Native 上进行性能分析的最佳方法。很大一部分文档已经过时,我们将尽最大努力在官方文档上创建拉取请求,或者至少在博客文章中写下我们的一些结论。
  • 正在将我们的导航解决方案切换到 react-navigation,所以我们可能很快会有一些反馈。
  • 我们在工具包中发布了一个新 HTML 组件,它能将原始 HTML 转换为 React Native 组件树。

Wix

  • 我们开始为 Metro Bundler 提交一个拉取请求,其中包含 react-native-repackager 的功能。我们已将 react-native-repackager 更新至支持 RN 44(我们用于生产环境)。我们将其用于 detox 的模拟基础设施。
  • 在过去的三个星期里,我们一直在用 detox 测试覆盖 Wix 应用。这对于如何在这种规模(超过 40 名工程师)的应用中减少手动 QA 来说,是一次了不起的学习经验。因此,我们解决了 detox 的几个问题,新版本刚刚发布。我很高兴地报告,我们正在践行“零不稳定性策略”,并且测试到目前为止一直稳定通过。
  • 适用于 Android 的 Detox 进展顺利。我们正在从社区获得大量帮助。我们预计在大约两周内发布初始版本。
  • 我们的性能测试工具 DetoxInstruments 的规模正在变得比我们最初设想的要大一些。我们现在计划将其转换为一个独立的工具,它将不再与 detox 紧密耦合。它将允许普遍地调查 iOS 应用的性能。它还将与 detox 集成,以便我们可以在性能指标上运行自动化测试。

下次会议

下一次会议定于 2017 年 8 月 16 日举行。由于这只是我们的第二次会议,我们想知道这些会议记录对 React Native 社区有何益处。如果您对我们如何改进会议成果有任何建议,请随时在 Twitter 上联系我

React Native 月报 #1

·阅读 6 分钟
Tomislav Tenodi
Shoutem 产品经理

Shoutem,我们很幸运能从 React Native 的早期阶段就开始与它合作。我们决定从第一天起就成为这个优秀社区的一员。很快,我们意识到几乎不可能跟上社区成长和改进的步伐。这就是为什么我们决定组织一个月度会议,所有主要的 React Native 贡献者都可以在会上简要介绍他们的工作和计划。

月度会议

我们在 2017 年 6 月 14 日举行了首次月度会议。React Native 月度会议的使命简单明了:改进 React Native 社区。展示团队的工作成果有助于各团队在线下进行协作。

团队

首次会议共有 8 个团队参加

我们希望有更多的核心贡献者加入未来的会议!

笔记

由于团队的计划可能会引起更广泛受众的兴趣,我们将在 React Native 博客上分享它们。所以,它们来了:

爱彼迎

  • 计划向 ViewAccessibilityInfo 原生模块添加一些 A11y(可访问性)API。
  • 将调查在 Android 上的原生模块中添加一些 API,以便能够指定它们运行的线程。
  • 一直在调查潜在的初始化性能改进。
  • 一直在研究一些更复杂的捆绑策略,以在“unbundle”的基础上使用。

Callstack

  • 正在研究通过使用 Detox 进行 E2E 测试来改进发布流程。拉取请求应该很快就会合并。
  • 他们一直在进行的 Blob 拉取请求已合并,后续拉取请求即将到来。
  • 增加内部项目对 Haul 的采用,以了解其与 Metro Bundler 相比的性能。正在与 webpack 团队合作,以提高多线程性能。
  • 他们在内部实施了更好的基础设施来管理开源项目。计划在未来几周内发布更多内容。
  • React Native 欧洲会议正在筹备中,目前还没有什么有趣的消息,但欢迎所有人参加!
  • 暂时退出了 react-navigation,以研究替代方案(特别是原生导航)。

Expo

Facebook

  • React Native 的打包器现在是独立的仓库中的 Metro Bundler。伦敦的 Metro Bundler 团队很高兴能满足社区的需求,提高模块化程度以支持 React Native 之外的更多用例,并提高对问题和 PR 的响应速度。
  • 在接下来的几个月里,React Native 团队将致力于完善原始组件的 API。预计将在布局怪癖、可访问性和流式类型方面有所改进。
  • React Native 团队今年还计划通过重构来改进核心模块化,以全面支持 Windows 和 macOS 等第三方平台。

GeekyAnts

  • 该团队正在开发一款 UI/UX 设计应用程序(代号:Builder),它直接与 .js 文件协同工作。目前,它只支持 React Native。它类似于 Adobe XD 和 Sketch。
  • 该团队正在努力工作,以便您可以在编辑器中加载现有 React Native 应用,进行更改(作为设计师,以可视化方式),并将更改直接保存到 JS 文件中。
  • 大家正在努力弥合设计师和开发者之间的鸿沟,让他们在同一个仓库中协作。
  • 此外,NativeBase 最近在 GitHub 上达到了 5,000 颗星。

Microsoft

  • CodePush 现已集成到 Mobile Center 中。这是在分发、分析和其他服务方面提供更集成体验的第一步。请在此处查看他们的公告:这里
  • VS Code 在调试方面有一个 bug,他们正在修复中,并会发布新的构建版本。
  • 正在调查 Detox 用于集成测试,正在研究 JSC Context 以获取变量以及崩溃报告。

Shoutem

  • 通过 React Native 社区的工具,使在 Shoutem 应用上的工作变得更容易。您将能够使用所有 React Native 命令来运行在 Shoutem 上创建的应用。
  • 正在调查 React Native 的性能分析工具。他们在设置过程中遇到了很多问题,他们将写下他们在此过程中发现的一些见解。
  • Shoutem 正在努力使 React Native 更容易与现有原生应用集成。他们将记录公司内部开发的概念,以获取社区的反馈。

Wix

  • 内部正在努力采用 Detox,以将 Wix 应用的很大一部分转变为“零手动 QA”。因此,Detox 正在被数十名开发人员在生产环境中大量使用,并迅速成熟。
  • 正在努力为 Metro Bundler 添加支持,以便在构建期间覆盖任何文件扩展名。除了“ios”和“android”之外,它还将支持任何自定义扩展名,如“e2e”或“detox”。计划将其用于 E2E 模拟。目前已经有一个名为 react-native-repackager 的库,现在正在处理一个 PR。
  • 正在调查性能测试的自动化。这是一个名为 DetoxInstruments 的新仓库。您可以查看,它正在开源开发中。
  • 正在与 KPN 的一位贡献者合作,开发适用于 Android 的 Detox 并支持真实设备。
  • 正在考虑将“Detox 作为平台”,以允许构建需要自动化模拟器/设备的其他工具。例如,React Native 的 Storybook 或 Ram 的集成测试想法。

下次会议

会议将每四周举行一次。下一次会议定于 2017 年 7 月 12 日举行。由于我们刚开始这种会议形式,我们想知道这些会议记录对 React Native 社区有何益处。如果您对我们在接下来的会议中应该涵盖哪些内容,或者我们应该如何改进会议成果有任何建议,请随时在 Twitter 上联系我

React Native 中更好的列表视图

·阅读 6 分钟
Spencer Ahrens
Facebook 软件工程师

在我们在社区群组中发布预告后,许多人已经开始试用我们的一些新列表组件,但我们今天正式宣布它们!不再有 ListViewDataSource,没有过时行、被忽略的错误或过多的内存消耗——通过最新的 React Native 2017 年 3 月发布候选版本(0.43-rc.1),您可以从新的组件套件中选择最适合您用例的组件,开箱即用,具有出色的性能和功能集。

<FlatList>

这是用于简单、高性能列表的主力组件。提供一个数据数组和一个 renderItem 函数即可。

<FlatList
data={[{title: 'Title Text', key: 'item1'}, ...]}
renderItem={({item}) => <ListItem title={item.title} />}
/>

<SectionList>

如果您想渲染一组按逻辑部分划分的数据,可能带有部分标题(例如在按字母排序的地址簿中),并且可能具有异构数据和渲染(例如包含一些按钮的个人资料视图,然后是撰写器,接着是照片网格,然后是朋友网格,最后是故事列表),这就是您应该选择的方式。

<SectionList
renderItem={({item}) => <ListItem title={item.title} />}
renderSectionHeader={({section}) => <H1 title={section.key} />}
sections={[ // homogeneous rendering between sections
{data: [...], key: ...},
{data: [...], key: ...},
{data: [...], key: ...},
]}
/>

<SectionList
sections={[ // heterogeneous rendering between sections
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
]}
/>

<VirtualizedList>

它是一个在幕后实现,具有更灵活的 API 的组件。如果您的数据不在普通数组中(例如,一个不可变列表),它会特别方便。

特性

列表在许多场景中都会使用,因此我们为新组件添加了丰富的功能,以开箱即用地处理大多数用例:

  • 滚动加载(onEndReached)。
  • 下拉刷新(onRefresh / refreshing)。
  • 可配置的可见性(VPV)回调(onViewableItemsChanged / viewabilityConfig)。
  • 水平模式(horizontal)。
  • 智能项目和节分隔符。
  • 多列支持(numColumns
  • scrollToEndscrollToIndexscrollToItem
  • 更好的 Flow 类型检查。

注意事项

  • 当内容滚动出渲染窗口时,项目子树的内部状态不会被保留。请确保您的所有数据都捕获在项目数据或外部存储中,如 Flux、Redux 或 Relay。

  • 这些组件基于 PureComponent,这意味着如果 props 保持浅层相等,它们将不会重新渲染。请确保您的 renderItem 函数直接依赖的所有内容都作为 prop 传递,并且在更新后不会出现 === 的情况,否则您的 UI 可能不会随着更改而更新。这包括 data prop 和父组件状态。例如:

    <FlatList
    data={this.state.data}
    renderItem={({item}) => (
    <MyItem
    item={item}
    onPress={() =>
    this.setState(oldState => ({
    selected: {
    // New instance breaks `===`
    ...oldState.selected, // copy old data
    [item.key]: !oldState.selected[item.key], // toggle
    },
    }))
    }
    selected={
    !!this.state.selected[item.key] // renderItem depends on state
    }
    />
    )}
    selected={
    // Can be any prop that doesn't collide with existing props
    this.state.selected // A change to selected should re-render FlatList
    }
    />
  • 为了限制内存并实现平滑滚动,内容会异步地在屏幕外渲染。这意味着滚动速度可能超过填充速度,并短暂看到空白内容。这是一种权衡,可以根据每个应用程序的需求进行调整,我们正在幕后努力改进它。

  • 默认情况下,这些新列表会在每个项目上查找 key prop 并将其用作 React key。或者,您可以提供一个自定义的 keyExtractor prop。

性能

除了简化 API 之外,新的列表组件还具有显著的性能增强,主要的一点是对于任意数量的行,内存使用几乎保持不变。这是通过“虚拟化”渲染窗口之外的元素来实现的,即完全从组件层次结构中卸载它们,并回收 React 组件的 JS 内存以及影子树和 UI 视图的本地内存。这有一个缺点,即内部组件状态不会被保留,因此请确保在组件本身之外跟踪任何重要状态,例如在 Relay、Redux 或 Flux 存储中。

限制渲染窗口也减少了 React 和原生平台需要完成的工作量,例如视图遍历。即使您正在渲染一百万个元素中的最后一个,使用这些新列表也无需迭代所有这些元素即可进行渲染。您甚至可以使用 scrollToIndex 跳转到中间而不会进行过多的渲染。

我们还在调度方面做出了一些改进,这应该有助于提高应用程序的响应速度。渲染窗口边缘的项目在任何活动手势、动画或其他交互完成后,以较低的优先级不频繁地渲染。

高级用法

ListView 不同,渲染窗口中的所有项目在任何 props 更改时都会重新渲染。通常这没有问题,因为窗口化将项目数量减少到恒定数量,但如果您的项目比较复杂,您应该确保遵循 React 的性能最佳实践,并在组件内部适当地使用 React.PureComponent 和/或 shouldComponentUpdate,以限制递归子树的重新渲染。

如果您可以在不渲染行的情况下计算其高度,可以通过提供 getItemLayout prop 来改善用户体验。这使得使用例如 scrollToIndex 滚动到特定项目更加流畅,并且会改善滚动指示器 UI,因为可以在不渲染内容的情况下确定其高度。

如果您有替代数据类型,例如不可变列表,那么 <VirtualizedList> 是您的最佳选择。它接受一个 getItem prop,允许您返回任何给定索引的项目数据,并且具有更宽松的流类型。

如果您有不寻常的用例,还可以调整许多参数。例如,您可以使用 windowSize 来权衡内存使用和用户体验,maxToRenderPerBatch 来调整填充率和响应速度,onEndReachedThreshold 来控制何时进行滚动加载,等等。

未来工作

  • 现有界面的迁移(最终将弃用 ListView)。
  • 根据需求增加更多功能(请告诉我们!)。
  • 支持粘性节标题。
  • 更多性能优化。
  • 支持带状态的功能性项目组件。