跳到主要内容

标记为“engineering”的帖子共 27 篇

查看所有标签

在 React Native 中使用 AWS

·9 分钟阅读
Richard Threlkeld
AWS Mobile 高级技术产品经理

AWS 在技术行业中以云服务提供商而闻名。这些服务包括计算、存储和数据库技术,以及完全托管的无服务器产品。AWS Mobile 团队一直与客户和 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) 代码与电子邮件或 SMS 一起使用。今天支持的类别有

  • 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 and Logging:提供国际化和本地化功能,以及调试和日志记录功能。

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。这使您能够将功能(例如 NoSQL 和全文搜索)组合到单个 GraphQL API 中作为模式。这使您可以混合和匹配数据源。AppSync 服务还可以 从模式进行配置,因此如果您不熟悉 AWS 服务,您可以编写 GraphQL SDL,单击一个按钮,您就可以自动启动并运行。

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

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

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

当您使用 AWSAppSyncClient 时,入门非常简单,它可以插入到 Apollo Client 中。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 Mobile 团队,获取 AWS AmplifyAWS AppSync 的信息。

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

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

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

一旦应用准备就绪,Twitter 徽标会愉快地展开,露出应用。

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


为了了解如何构建它,我首先必须了解加载动画的不同部分。看到微妙之处的最简单方法是放慢速度。

这里有几个主要部分,我们需要弄清楚如何构建。

  1. 缩放小鸟。
  2. 随着小鸟长大,显示下方的应用
  3. 在最后稍微缩小应用

我花了好一会儿才弄清楚如何制作这个动画。

我一开始做了一个错误的假设,即蓝色背景和 Twitter 小鸟是位于应用顶部的图层,并且随着小鸟的增长,它变得透明,从而露出了下方的应用。这种方法行不通,因为 Twitter 小鸟变得透明会显示蓝色图层,而不是下方的应用!

对您来说幸运的是,亲爱的读者,您不必经历我经历过的同样的挫败感。您将获得这个很好的教程,直接跳到精彩部分!


正确的方法

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

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

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


此动画的主要技巧是使用 Twitter 徽标作为蒙版,并蒙版应用和白色图层。我不会深入探讨蒙版的细节,有很多 很多 资源 在线 介绍了。

此上下文中的蒙版基础知识是拥有图像,其中蒙版的不透明像素显示它们正在蒙版的内容,而蒙版的透明像素隐藏它们正在蒙版的内容。

我们使用 Twitter 徽标作为蒙版,并使其蒙版两个图层;纯白色图层和应用图层。

为了露出应用,我们将蒙版放大,直到它比整个屏幕都大。

在蒙版放大时,我们淡入应用图层的不透明度,显示应用并隐藏其后面的纯白色图层。为了完成效果,我们以比例 > 1 启动应用图层,并在动画结束时将其缩小到 1。然后,我们隐藏非应用图层,因为它们永远不会再被看到。

俗话说,一张图片胜过千言万语。交互式可视化值多少字?单击“下一步”按钮浏览动画。显示图层为您提供侧视图视角。网格在那里是为了帮助可视化透明图层。

现在,针对 React Native

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

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

import {MaskedViewIOS} from 'react-native';

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

MaskedViewIOS 接受 props maskElementchildren。children 由 maskElement 蒙版。请注意,蒙版不需要是图像,它可以是任何任意视图。上面示例的行为是渲染蓝色视图,但仅当单词“Basic Mask”来自 maskElement 时才可见。我们刚刚制作了复杂的蓝色文本。

我们想要做的是渲染我们的蓝色图层,然后在顶部使用 Twitter 徽标渲染我们的蒙版应用和白色图层。

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

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

现在是 Animated 部分

我们拥有使此工作所需的所有部分,下一步是为它们制作动画。为了使此动画感觉良好,我们将使用 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.timing 和单个 Animated.Value

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

由于我将此动画视为在整个动画的不同时间点发生的步骤,因此我们将从 0 开始我们的 Animated.Value,表示 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% 时,它应具有 .8 的比例值,然后再放大到最后的比例 70。说实话,选择 70 是相当随意的,它需要足够大才能完全露出屏幕,而 60 不够大 😀。关于这部分有趣的是,数字越高,它看起来增长得越快,因为它必须在相同的时间内到达那里。这个数字经过了一些反复试验才使它与此徽标看起来不错。不同尺寸的徽标/设备将需要不同的结束比例,以确保整个屏幕都被露出。

应用应保持不透明一段时间,至少在 Twitter 徽标变小期间。根据官方动画,我希望在小鸟放大到一半时开始显示它,并在整个动画进行到 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. 这本 gitbook 是在您阅读 React Native 文档后学习有关 Animated 的更多知识的绝佳资源。
  2. 实际的 Twitter 动画似乎在接近尾声时加速了蒙版显示。尝试修改加载器以使用不同的缓动函数(或弹簧动画!)以更好地匹配该行为。
  3. 当前蒙版的最终比例是硬编码的,可能无法在平板电脑上完全显示整个应用程序。根据屏幕尺寸和图像尺寸计算最终比例将是一个很棒的 PR。

React Native 月刊 #6

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

React Native 每月例会仍在如火如荼地进行!请务必查看本文底部的注释,了解下次会议的信息。

Expo

  • 祝贺 Devin AbbottHoussein Djirdeh 预发布了《Full Stack React Native》一书!它通过构建几个小型应用程序来引导您学习 React Native。您可以在购买本书之前在 https://www.fullstackreact.com/react-native/ 上试用这些应用程序。
  • 发布了 reason-react-native-scripts 的第一个(实验性)版本,以帮助人们轻松试用 ReasonML
  • Expo SDK 24 已发布!它使用 React Native 0.51,并包含许多新功能和改进:在独立应用程序中捆绑图像(无需在首次加载时缓存!)、图像处理 API(裁剪、调整大小、旋转、翻转)、人脸检测 API、新的发布渠道功能(为给定渠道设置活动发布和回滚)、用于跟踪独立应用程序构建的 Web 仪表板,以及修复了 OpenGL Android 实现和 Android 多任务处理器的长期存在的错误,仅举几例。
  • 从今年 1 月开始,我们将为 React Navigation 分配更多资源。我们坚信,仅使用 React 组件和诸如 Animated 和 react-native-gesture-handler 之类的基元来构建 React Native 导航是可能且可取的,并且我们对计划中的一些改进感到非常兴奋。如果您希望为社区做出贡献,请查看 react-native-mapsreact-native-svg,这两个项目都需要一些帮助!

Infinite Red

Microsoft

  • 已启动一个 pull request,以将核心 React Native Windows 桥迁移到 .NET Standard,使其有效地与操作系统无关。希望许多其他 .NET Core 平台可以使用自己的线程模型、JavaScript 运行时和 UIManager(例如 JavaScriptCore、Xamarin.Mac、Linux Gtk# 和 Samsung Tizen 选项)来扩展该桥。

Wix

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

下次会议

已经有一些关于重新调整本次会议用途以讨论单一且特定主题(例如,导航、将 React Native 模块移动到单独的仓库、文档等)的讨论。 这样,我们认为我们可以为 React Native 社区做出最大的贡献。 这可能会在下次会议中进行。 欢迎在 Twitter 上发布您希望作为主题涵盖的内容。

React Native 月刊 #5

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

React Native 每月例会继续进行!让我们看看我们的团队在做什么。

Callstack

  • 我们一直在开发 React Native CI。 最重要的是,我们已经从 Travis 迁移到 Circle,为 React Native 留下了一个单一的、统一的 CI 管道。
  • 我们组织了 Hacktoberfest - React Native 版本,在其中,我们与与会者一起尝试向开源项目提交许多 pull request。
  • 我们一直在开发 Haul。 上个月,我们提交了两个新版本,包括 webpack 3 支持。 我们计划添加 CRNAExpo 支持,并致力于改进 HMR。 我们的路线图在 issue tracker 上公开。 如果您想提出改进建议或提供反馈,请告诉我们!

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 支持
    • 我们正在引入许多方向感知样式。
      • 位置
        • (左|右) → (开始|结束)
      • 外边距
        • margin(左|右) → margin(开始|结束)
      • 内边距
        • padding(左|右) → padding(开始|结束)
      • 边框
        • borderTop(左|右)Radius → borderTop(开始|结束)Radius
        • borderBottom(左|右)Radius → borderBottom(开始|结束)Radius
        • border(左|右)Width → border(开始|结束)Width
        • border(左|右)Color → border(开始|结束)Color
    • 在 RTL 中,对于位置、外边距、内边距和边框样式,“left”和“right”的含义被交换了。 在几个月内,我们将删除此行为,并使“left”始终表示“left”,而“right”始终表示“right”。 破坏性更改隐藏在一个标志下。 在您的 React Native 组件中使用 I18nManager.swapLeftAndRightInRTL(false) 以选择加入它们。
  • 正在开发 Flow,为我们的内部原生模块添加类型,并使用这些类型在 Java 中生成接口,在 ObjC 中生成原生实现必须实现的协议。 我们希望此代码生成最早在明年开源。

Infinite Red

  • 用于帮助 React Native 和其他项目的新 OSS 工具。 更多信息请点击此处
  • 改进 Ignite 以发布新的样板(代号:Bowser)

Shoutem

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

下次会议

下次会议定于 2017 年 12 月 6 日星期三。如果您对我们应如何改进会议输出有任何建议,请随时在 Twitter 上 ping 我。

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 中的一些错误修复/可靠性改进/新功能,包括视频录制、新的启动画面 API、对 react-native-gesture-handler 的支持以及改进的错误处理。
  • 关于:react-native-gesture-handlerSoftware MansionKrzysztof Magiera 继续推进这项工作,我们一直在帮助他进行测试并资助他的一部分开发时间。 将其集成到 SDK21 中的 Expo 中将使人们可以在 Snack 中轻松使用它,因此我们很高兴看到人们会提出什么。
  • 关于:改进的错误日志记录/处理 - 有关日志记录的详细信息,请参阅 此内部 Expo PR 的 gist(特别是“问题 2”),以及 此提交,了解处理导入 npm 标准库模块失败的尝试的更改。 在 React Native 中,有很多机会以上游方式改进错误消息,我们将致力于跟进上游 PR。 社区参与进来也会很棒。
  • native.directory 继续增长,您可以从 GitHub repo 添加您的项目。
  • 访问北美各地的黑客马拉松,包括 PennAppsHack The NorthHackMIT,以及即将到来的 MHacks

Facebook

  • 致力于改进 Android 上的 <Text><TextInput> 组件。 (<TextInput> 的原生自动增长;深度嵌套的 <Text> 组件布局问题;更好的代码结构;性能优化)。
  • 我们仍在寻找更多贡献者,他们愿意帮助分类问题和 pull request。

Microsoft

  • 为 CodePush 发布了代码签名功能。 React Native 开发人员现在可以在 CodePush 中签署他们的应用程序 bundle。 公告可以在此处找到
  • 致力于完成 CodePush 与 Mobile Center 的集成。 也在考虑测试/崩溃集成。

下次会议

下次会议定于 2017 年 10 月 10 日星期三。由于这只是我们的第四次会议,我们想知道这些笔记如何使 React Native 社区受益。 如果您对我们应如何改进会议输出有任何建议,请随时在 Twitter 上 ping 我。

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。
  • 发布了带有相机、支付、安全存储、磁力计、暂停/恢复 fs 下载以及改进的启动/加载屏幕的 SDK20。
  • 继续与 Krzysztof 合作开发 react-native-gesture-handler。 请试用一下,重建一些您以前使用 PanResponder 或原生手势识别器构建的手势,并让我们知道您遇到的问题。
  • 正在试验 JSC 调试协议,并在 Canny 上处理大量功能请求。

Facebook

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

Microsoft

  • 新的 Skype 应用程序构建在 React Native 之上,以便于在平台之间尽可能多地共享代码。 基于 React Native 的 Skype 应用程序目前在 Android 和 iOS 应用商店中可用。
  • 在基于 React Native 构建 Skype 应用程序时,我们会向 React Native 发送 pull request,以解决我们遇到的错误和缺少的功能。 到目前为止,我们已经合并了大约 70 个 pull request
  • 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 FAQ 中简要介绍了这些库的方法有何不同。

Shoutem

  • 我们正在继续努力改进和简化在使用 Shoutem 构建应用程序时的开发人员体验。
  • 开始将我们的所有应用程序迁移到 react-navigation,但我们最终将其推迟到发布更稳定的版本或本地导航解决方案之一变得稳定为止。
  • 将我们的所有 扩展 和我们的大多数开源库(animationthemeui)更新到 React Native 0.47.1。

下次会议

下次会议定于 2017 年 9 月 13 日星期三。 由于这只是我们的第三次会议,我们想知道这些笔记如何使 React Native 社区受益。 如果您对我们应如何改进会议输出有任何建议,请随时在 Twitter 上 ping 我。

React Native 在 Marketplace 中的性能表现

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

React Native 在 Facebook 系列的多个应用程序的多个位置中使用,包括主 Facebook 应用程序中的顶级选项卡。 我们这篇文章的重点是一个高度可见的产品,Marketplace。 它在十几个左右的国家/地区可用,使用户能够发现其他用户提供的产品和服务。

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

典型的 React Native 启动看起来像这样

免责声明:比例不具有代表性,并且会因 React Native 的配置和使用方式而异。

我们首先初始化 React Native 核心(又名“Bridge”),然后再运行产品特定的 JavaScript,该 JavaScript 确定 React Native 将在原生处理时间中渲染哪些原生视图。

一种不同的方法

我们犯的早期错误之一是让 Systrace 和 CTScan 驱动我们的性能工作。 这些工具帮助我们在 2016 年找到了许多唾手可得的成果,但我们发现 Systrace 和 CTScan 都不能代表生产场景,也无法模拟野外发生的情况。 分解中花费的时间比率通常是不正确的,有时会严重偏离基线。 在极端情况下,我们期望花费几毫秒的时间实际上花费了数百或数千毫秒。 也就是说,CTScan 很有用,我们发现它在回归影响生产之前捕获了三分之一的回归。

在 Android 上,我们将这些工具的缺点归因于以下事实:1) React Native 是一个多线程框架,2) Marketplace 与大量复杂视图(例如 Newsfeed 和其他顶级选项卡)位于同一位置,以及 3) 计算时间差异很大。 因此,在今年下半年,我们让生产测量和分解驱动了我们几乎所有的决策和优先级排序。

生产工具化的道路

对生产进行工具化表面上听起来很简单,但事实证明这是一个相当复杂的过程。 这花费了多个迭代周期,每个周期为 2-3 周; 由于将提交登陆到 master、将应用程序推送到 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 能够与使用 Native 构建的类似产品相媲美,并且总的来说,React Native 性能能够与原生性能相提并论。此外,尽管我们在今年上半年大幅降低了约 80% 的桥接启动成本,但我们计划通过诸如 Prepack 和更多的构建时处理等项目,将 React Native 桥接的成本降至接近于零。

React Native 月刊 #2

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

React Native 每月会议继续进行!在本次会议上,我们邀请了 Infinite RedChain React,React Native 会议 背后的杰出团队。由于这里的大多数人都在 Chain React 会议上发表演讲,我们将会议推迟了一周。会议的演讲已发布到网上,我鼓励您查看一下。那么,让我们看看我们的团队在忙些什么。

团队

在第二次会议上,我们有 9 个团队加入我们

笔记

以下是每个团队的笔记

Airbnb

  • 查看 Airbnb 仓库 以了解与 React Native 相关的项目。

Callstack

  • Mike Grabowski 一如既往地管理着 React Native 的每月发布,包括一些已发布的 beta 版本。特别是,致力于将 v0.43.5 版本发布到 npm,因为它解锁了 Windows 用户!
  • 关于 Haul 的缓慢但持续的工作正在进行中。有一个 pull request 添加了 HMR,其他改进也已发布。最近,一些行业领导者开始采用它。可能计划开始在该领域进行全职有偿工作。
  • 来自 Jest 团队的 Michał Pierzchała 本月加入了我们在 Callstack 的团队。他将帮助维护 Haul,并可能参与 Metro BundlerJest 的工作。
  • Satyajit Sahoo 现在和我们在一起了,太棒了!
  • 我们的 OSS 部门即将推出一系列很酷的东西。特别是,致力于将 Material Palette API 引入 React Native。计划最终发布我们的原生 iOS 工具包,旨在提供与原生组件 1:1 的外观和感觉。

Expo

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

Facebook

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

GeekyAnts

  • 我们在 Chain React 会议上演示了 Designer Tool,它可以与 React Native 文件一起使用。许多与会者注册了候补名单。
  • 我们还在研究其他跨平台解决方案,例如 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 测试应用程序 - 这是 ReactNative 架构独有的功能。
  • VS Code 在调试 ReactNative 方面存在已知问题 - 几天后的下一个扩展版本将修复该问题。
  • 由于 Microsoft 内部还有许多其他团队也在从事 React Native 的工作,我们将努力在下次会议上获得所有小组的更好代表。

Shoutem

  • 完成了使 Shoutem 上的 React Native 开发更容易的过程。在 Shoutem 上开发应用程序时,您可以使用所有标准的 react-native 命令。
  • 我们做了大量工作,试图弄清楚如何在 React Native 上最好地进行性能分析。很大一部分 文档 已经过时,我们将尽最大努力在官方文档上创建一个 pull request,或者至少在一篇博客文章中写下我们的一些结论。
  • 将我们的导航解决方案切换到 react-navigation,因此我们可能很快会收到一些反馈。
  • 我们在我们的工具包中发布了 一个新的 HTML 组件,它将原始 HTML 转换为 React Native 组件树。

Wix

  • 我们开始致力于向 Metro Bundler 提交 pull request,其中包含 react-native-repackager 功能。我们更新了 react-native-repackager 以支持 RN 44(我们在生产中使用它)。我们正在将其用于我们 detox 的模拟基础设施。
  • 在过去的三周里,我们一直在 detox 测试中覆盖 Wix 应用程序。这是一个关于如何在如此规模的应用程序(超过 40 名工程师)中减少手动 QA 的惊人学习体验。我们因此解决了 detox 的几个问题,新版本刚刚发布。我很高兴地报告,我们正在兑现“零抖动策略”,到目前为止,测试一直稳定通过。
  • Detox for Android 正在顺利进行中。我们正在获得社区的大力帮助。我们预计在两周左右的时间内发布初始版本。
  • DetoxInstruments,我们的性能测试工具,变得比我们最初预期的要大一些。我们现在计划将其转变为一个独立工具,它不会与 detox 紧密耦合。它将允许调查 iOS 应用程序的总体性能。它还将与 detox 集成,以便我们可以对性能指标运行自动化测试。

下次会议

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

React Native 月刊 #1

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

Shoutem,我们很幸运地从 React Native 的早期就开始与其合作。我们决定从第一天起就成为这个令人惊叹的社区的一部分。很快,我们意识到几乎不可能跟上社区发展和改进的步伐。这就是我们决定组织每月会议的原因,所有主要的 React Native 贡献者都可以在会上简要介绍他们的努力和计划。

每月会议

我们在 2017 年 6 月 14 日举行了第一次每月会议。React Native 每月会议的任务简单而直接:改进 React Native 社区。展示团队的努力可以促进团队之间在线下进行的协作。

团队

在第一次会议上,我们有 8 个团队加入我们

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

笔记

由于团队的计划可能对更广泛的受众感兴趣,我们将在 React Native 博客上分享它们。所以,这就是它们

Airbnb

  • 计划向 ViewAccessibilityInfo 原生模块添加一些 A11y(辅助功能)API。
  • 将研究向 Android 上的原生模块添加一些 API,以允许指定它们运行的线程。
  • 一直在调查潜在的初始化性能改进。
  • 一直在调查一些更复杂的打包策略,以便在“unbundle”之上使用。

Callstack

  • 正在考虑通过使用 Detox 进行 E2E 测试来改进发布流程。Pull request 应该很快就会落地。
  • 他们一直在处理的 Blob pull request 已合并,后续的 pull request 即将到来。
  • 增加 Haul 在内部项目中的采用率,以了解其与 Metro Bundler 相比的性能。正在与 webpack 团队合作,以获得更好的多线程性能。
  • 在内部,他们已经实施了更好的基础设施来管理开源项目。计划在未来几周内发布更多内容。
  • React Native Europe 会议即将到来,目前还没有什么有趣的事情,但欢迎大家参加!
  • 暂时退出了 react-navigation 一段时间,以研究替代方案(特别是原生导航)。

Expo

Facebook

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

GeekyAnts

  • 该团队正在开发一个 UI/UX 设计应用程序(代号:Builder),该应用程序直接与 .js 文件一起工作。目前,它仅支持 React Native。它类似于 Adobe XD 和 Sketch。
  • 该团队正在努力使您能够在编辑器中加载现有的 React Native 应用程序,进行更改(可视化地,作为设计师),并将更改直接保存到 JS 文件中。
  • 人们正在努力弥合设计师和开发者之间的差距,并将他们聚集在同一个仓库中。
  • 此外,NativeBase 最近达到了 5,000 个 GitHub stars。

Microsoft

  • CodePush 现已集成到 Mobile Center 中。这是提供与分发、分析和其他服务更集成体验的第一步。请参阅他们的公告 此处
  • VS Code 在调试方面存在一个错误,他们正在努力立即修复该错误,并将发布一个新的构建版本。
  • 正在调查 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 的贡献者合作开发 Detox for Android 并支持真机。
  • 正在考虑将“Detox 作为一个平台”,以允许构建其他需要自动化模拟器/设备的工具。一个例子是用于 React Native 的 Storybook 或 Ram 关于集成测试的想法。

下次会议

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

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。如果您的数据不在纯数组中(例如,不可变列表),则尤其方便。

功能

列表在许多上下文中使用,因此我们在新的组件中 packed 了大量功能,以开箱即用地处理大多数用例

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

一些注意事项

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

  • 这些组件基于 PureComponent,这意味着如果 props 保持浅相等,它们将不会重新渲染。确保您的 renderItem 函数直接依赖的所有内容都作为 props 传递,这些 props 在更新后不是 ===,否则您的 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 键。或者,您可以提供自定义 keyExtractor prop。

性能

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

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

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

高级用法

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

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

如果您有其他数据类型,例如不可变列表,则 <VirtualizedList> 是最佳选择。它接受一个 getItem prop,使您可以返回任何给定索引的项目数据,并具有更宽松的 flow 类型。

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

未来工作

  • 现有表面的迁移(最终弃用 ListView)。
  • 随着我们看到/听到需求,更多功能(请告诉我们!)。
  • 粘性节标题支持。
  • 更多性能优化。
  • 支持带有状态的功能项目组件。