原文:https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024
译者:ChatGPT 4 Turbo
编者注:几个新接收到的信息,1)文档元数据,代替之前 React Helmet 的功能,但支持 Client、SSR 和 RSC,2)资源加载,React 官方提供了资源加载相关的 API,主要是给框架开发者结合路由预加载使用,3)React 下个版本是 React 19,4)OffScreen 更名为 Activity 的原因是「不可见」不能反应某些场景下的含义,比如模态窗口后面的内容只是不活跃而不是不可见。
February 15, 2024 by Joseph Savona, Ricky Hanlon, Andrew Clark, Matt Carroll, and Dan Abramov.
在 React Labs 帖子中,我们会撰写关于正在积极研究和开发中的项目。自上次更新以来,我们已取得了重大进展,我们想要分享我们的进展。
React 编译器
React Compiler 已不再是一个研究项目:该编译器现在已在 instagram.com 的生产环境中得到应用,我们正在努力将编译器推广到 Meta 的更多平台,并准备首次开源发布。
正如我们在之前的帖子中讨论的,当状态改变时,React 有时会过度重新渲染。自 React 早期以来,我们对这类情况的解决方案一直是手动记忆化。在我们当前的 API 中,这意味着应用 useMemo
、 useCallback
和 memo
API 来手动调整 React 在状态变化时重新渲染的程度。但是手动 memo 是一种妥协。它使我们的代码变得杂乱,容易出错,且需要额外的工作来保持更新。
手动 memo 是一个合理的折中方案,但我们并不满足。我们的愿景是,当状态发生变化时,React 能够自动重新渲染 UI 的恰当部分,而不损害 React 核心心智模型。我们相信,React 的方法 —— UI 作为状态的简单函数,使用标准的 JavaScript 值和习语 —— 是 React 能够吸引如此多开发者的关键部分。这就是为什么我们投资构建了一个针对 React 的优化编译器。
JavaScript 是一种因其宽松的规则和动态特性而臭名昭著的难以优化的语言。React 编译器能够通过对 JavaScript 的规则和“React 的规则”进行建模来安全地编译代码。例如,React 组件必须是幂等的 —— 给定相同的输入必须返回相同的值 —— 并且不能改变 props 或 state 的值。这些规则限制了开发者可以做的事情,并帮助为编译器的优化划出了一个安全的空间。
当然,我们理解开发者有时会稍微弯曲一些规则,我们的目标是让 React 编译器尽可能地开箱即用。编译器会尝试检测代码是否严格遵循 React 的规则,并会在安全的情况下编译代码,或者在不安全的情况下跳过编译。我们正在对 Meta 的庞大且多样的代码库进行测试,以帮助验证这种方法。
对于好奇如何确保他们的代码遵循 React 规则的开发者,我们建议启用严格模式并配置 React 的 ESLint 插件。这些工具可以帮助捕捉 React 代码中的微妙错误,提高你今天的应用质量,并为即将到来的功能,如 React 编译器,使你的应用具备未来兼容性。我们还在整合 React 规则的文档,并更新我们的 ESLint 插件,以帮助团队理解和应用这些规则,创建更健壮的应用。
要看到编译器的实际运作,你可以查看我们去年秋天的演讲。在演讲时,我们有来自尝试在 instagram.com 的一个页面上使用 React 编译器的早期实验数据。从那以后,我们将编译器部署到了 instagram.com 的生产环境中。我们还扩大了团队,以加速在 Meta 的其他平台以及开源社区中的推广。我们对未来的道路感到兴奋,并将在未来几个月内分享更多信息。
Actions
我们之前提到过,我们正在探索使用 Server Actions 从客户端向服务器发送数据的解决方案,以便您可以执行数据库变更和实现表单。在 Server Actions 的开发过程中,我们扩展了这些 API,以便也支持仅客户端应用程序中的数据处理。
我们将这一更广泛的功能集合简称为“Actions”。Actions 允许你将一个函数传递给 DOM 元素,例如 <form/>
:
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
action
函数可以同步或异步操作。你可以在客户端使用标准 JavaScript 或在服务器端使用 'use server'
指令来定义它们。当使用一个动作时,React 将为你管理数据提交的生命周期,提供像 useFormStatus
和 useFormState
这样的钩子来访问表单动作的当前状态和响应。
默认情况下,Actions 会在过渡中提交,保持当前页面在操作处理时的交互性。由于操作支持异步函数,我们还增加了在过渡中使用 async/await
的能力。这允许你在像 fetch
这样的异步请求开始时,通过过渡的 isPending
状态显示待处理的 UI,并在更新应用的整个过程中显示待处理的 UI。
我们正在引入一个名为 useOptimistic
的功能,用于管理乐观状态更新。通过这个钩子,你可以应用临时更新,一旦最终状态提交后,这些更新会自动还原。对于 Actions 来说,这允许你在客户端乐观地设置数据的最终状态,假设提交是成功的,并在从服务器收到数据后还原到该值。它使用常规的 async
/ await
工作,所以无论你是在客户端使用 fetch
,还是在服务器使用 Server Action,它的工作方式都是相同的。
库作者可以在他们自己的组件中使用 action={fn}
属性来实现自定义的 useTransition
。我们的意图是为了让库在设计他们的组件 API 时采用 Actions 模式,以为 React 开发者提供一致的体验。例如,如果你的库提供了一个 <Calendar onSelect={eventHandler}>
组件,也考虑暴露一个 <Calendar selectAction={action}>
API。
虽然我们最初专注于用于客户端-服务器数据传输的 Server Actions,但我们对 React 的理念是在所有平台和环境中提供相同的编程模型。只要可能,如果我们在客户端引入一个功能,我们就会努力使其也能在服务器上运行,反之亦然。这种理念使我们能够创建一套无论你的应用在哪里运行都能工作的 API,从而使得之后升级到不同环境变得更加容易。
现在 Canary 频道已支持 Actions,并将在下一个 React 版本中发布。
React Canary 中的新功能
我们推出了 React Canaries,作为一种选择,可以在新的稳定功能设计接近最终版时就采用,而不必等到它们在稳定的 semver 版本中发布。
Canaries 是我们开发 React 的一种变革。以前,功能会在 Meta 内部私下研究和构建,因此用户只有在功能发布到 Stable 版本时才能看到最终打磨的产品。通过 Canaries,我们在公众和社区的帮助下进行构建,以完成我们在 React Labs 博客系列中分享的功能。这意味着您可以更早地了解新功能,因为它们正在被最终确定,而不是在它们完成之后。
React Server Components、Asset Loading、Document Metadata 和 Actions 已经在 React Canary 中发布,我们已经在 react.dev 上为这些功能添加了文档:
-
指令:
"use client"
和"use server"
是为全栈 React 框架设计的打包工具特性。它们标记了两种环境之间的“分割点”:"use client"
指导打包工具生成一个<script>
标签(如 Astro Islands),而"use server"
告诉打包工具生成一个 POST 端点(如 tRPC Mutations)。它们一起让你编写可复用的组件,将客户端交互性与相关的服务器端逻辑结合起来。 -
文档元数据:我们添加了内置支持,在您的组件树中的任何位置渲染
<title>
、<meta>
和元数据<link>
标签。这些在所有环境中的工作方式相同,包括完全的客户端代码、SSR 和 RSC。这为像 React Helmet 这样的库开创的功能提供了内置支持。 -
资源加载:我们将 Suspense 与样式表、字体和脚本等资源的加载生命周期集成在一起,以便 React 考虑它们来确定像
<style>
、<link>
和<script>
这样的元素中的内容是否准备好显示。我们还添加了像preload
和preinit
这样的新资源加载 API,以便更好地控制资源应何时加载和初始化。 -
Actions:如上所述,我们已经添加了操作来管理从客户端向服务器发送数据。您可以向像
<form/>
这样的元素添加action
,使用useFormStatus
访问状态,用useFormState
处理结果,并且用useOptimistic
乐观地更新 UI。
由于所有这些功能都是相互协作的,因此很难单独在 Stable 频道中发布它们。如果没有用于访问表单状态的补充钩子,发布 Actions 将限制 Actions 的实际可用性。如果不集成 Server Actions,引入 React 服务器组件将使在服务器上修改数据变得复杂。
在我们将一系列功能发布到 Stable 频道之前,我们需要确保它们能够协同工作,并且开发者拥有在生产中使用它们所需的一切。React Canaries 让我们能够单独开发这些功能,并逐步发布稳定的 API,直到整个功能集完成。
React Canary 当前的功能集已经完整,准备好发布了。
React 的下一个主要版本
经过几年的迭代, react@canary
现在已经准备好发布到 react@latest
。上面提到的新功能与您的应用程序运行的任何环境都兼容,提供了生产使用所需的一切。由于资产加载和文档元数据可能会对一些应用程序造成重大变化,React 的下一个版本将是一个主要版本:React 19。
在 React 19 中,我们还添加了长期以来被请求的改进,这些改进需要进行破坏性更改,比如对 Web Components 的支持。我们现在的重点是落实这些更改,准备发布,完成新功能的文档,并发布包含的内容公告。
我们将在未来几个月内分享更多关于 React 19 包含的所有内容、如何采用新的客户端功能以及如何构建对 React 服务器组件的支持的信息。
Offscreen(更名为 Activity)
自从我们上次更新以来,我们将正在研究的一个功能从“Offscreen”重命名为“Activity”。原来的名字“Offscreen”暗示它只适用于应用程序中不可见的部分,但在研究该功能时,我们意识到应用程序的某些部分可能是可见的但不活跃的,比如模态窗口后面的内容。新名称更准确地反映了将应用程序的某些部分标记为“活跃”或“不活跃”的行为。
Activity 仍在研究中,我们剩余的工作是确定暴露给库开发者的原始数据类型。在我们专注于发布更加完整的功能时,我们已经降低了这一领域的优先级。
除了这次更新,我们的团队还在会议上发表演讲,并在播客节目中露面,更多地讲述我们的工作并回答问题。
- Sathya Gunasekaran 在 React India 会议上讲述了 React 编译器
- Dan Abramov 在 RemixConf 上发表了题为“来自另一个维度的 React”的演讲,探讨了 React 服务器组件和 Actions 可能的替代历史
- Dan Abramov 在 Changelog 的 JS Party 播客上接受了关于 React 服务器组件的采访
- Matt Carroll 在 Front-End Fire 播客上接受了采访,他在其中讨论了 The Two Reacts
Thanks Lauren Tan, Sophie Alpert, Jason Bonta, Eli White, and Sathya Gunasekaran for reviewing this post.
感谢阅读,我们 React Conf 见!