大家好,这里是大家的林语冰。坚持阅读,自律打卡,每天一次,进步一点。
免责声明
本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考。英文原味版请传送 React Labs: What We've Been Working On。
本期共享的是 ------ 自上次更新以来 React 实验室关于 React 18 进一步的研究成果,以及 React 19 的前瞻性功能。
React 编译器
React 编译器不再是一个研究项目:该编译器现在用于驱动 instagram.com 的生产环境,我们正在努力将编译器搬运到 Meta(前脸书)的其他平台,并准备首个开源版本。
当状态变化时,React 有时会过量重新渲染。自 React 早期以来,我们针对此类情况的解决方案一直是手动记忆化。在目前的 API 中,这意味着,应用 useMemo/useCallback/memo
API,手动调整状态更改时 React 重新渲染的程度。但手动记忆化是一种妥协。这使代码变得混乱,容易出错,且需要额外的工作才能保持最新状态。
手动记忆化是一个合理的妥协,但我们欲求不满。我们的愿景是,当状态变化时,React 能够自动重新渲染 UI 的正确部分,而不影响核心心智模型。我们相信 React 的方案,即 UI 作为一个简单的状态函数,具有标准的 JS 值和习惯用法,是 React 能够被海量开发者青睐的关键所在。这就是我们投资构建 React 优化编译器的原因。
由于 JS 宽松的规则和动态特性,JS 是一种臭名昭著的、难以优化的语言。React 编译器能够通过对 JS 规则和"React 规则"建模,安全地编译代码。举个栗子,React 组件必须是幂等的,即给定相同的输入返回相同的值,且不能改变 props
或 state
的值。这些规则限制了开发者的所作所为,并有助于为编译器优化开辟安全空间。
当然,我们理解开发者有时会稍微改变规则,我们的目标是让 React 编译器在尽量多的代码上开箱即用。编译器会尝试检测代码何时不严格遵循 React 规则,并且会在安全的情况下编译代码,或者在不安全的情况下跳过编译。我们正在测试 Meta 的大型且多样化的代码库,辅助验证这种方案。
对于想要确保代码遵循 React 规则的开发者,我们建议启用严格模式,并配置 React 的 ESLint 插件。这些工具可以辅助捕获代码中的细微错误,提高当前 App 的质量,并为 App 提供面向未来的功能,比如 React 编译器。我们还致力于 React 规则的综合文档以及 ESLint 插件的更新,辅助团队理解和应用这些规则来创建更给力的 App。
要了解编译器的实际情况,您可以查看我们去年秋天的演讲。在演讲时,我们在 instagram.com 的一页上获得了尝试 React 编译器的早期实验数据。从那时起,我们通过 instagram.com 将编译器投入生产。我们还扩大了团队,加速在 Meta 和开源领域的其他应用的推出。我们对未来的道路感到鸡冻,且会在未来几个月共享更多内容。
Action
我们正在探索使用 Server Action(服务器操作)将数据从客户端发送到服务器的解决方案,这样我们可以执行数据库变更并实现表单。在 Server Action 的开发过程中,我们扩展了这些 API,从而支持纯客户端 App 中的数据处理。
jsx
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
action
函数可以同步或异步操作。我们可以使用标准 JS 在客户端定义它们,也可以使用 'use server'
指令在服务器上定义它们。使用 action
时,React 会为我们管理数据提交的生命周期,提供 useFormStatus
和 useFormState
等钩子,访问表单操作的当前状态和响应。
默认情况下,action
在 transition
里提交,这样在处理 action
时,可以保持当前页面的交互性。由于 action
支持异步函数,我们还添加了在 transition
中使用 async/await
的功能。这允许我们在 fetch
等异步请求启动时,显示 transition
的 isPending
状态的待定 UI,并在应用更新的整个过程中显示待定 UI。
除了 action
之外,我们还引入了一项名为 useOptimistic
的功能,用于管理积极状态更新。使用此钩子,我们可以应用临时更新,一旦最终状态提交,这些更新就会自动恢复。对于 action
,假设提交成功,这允许我们乐观地设置客户端上数据的最终状态,并恢复为从服务器接收的数据的值。它使用常规 async/await
奏效,因此无论是我们在客户端上使用 fetch
,还是来自服务器的 Sever Action,其工作原理都相同。
库作者可以使用 useTransition
在自己的组件中实现自定义 action={fn}
props。我们的目的是让库在设计组件 API 时采用 Actions 模式,为 React 开发者提供一致的体验。举个栗子,如果您的库提供了 <Calendar onSelect={eventHandler}>
组件,也请考虑暴露 <Calendar selectAction={action}>
API。
虽然我们最初聚焦于于客户端-服务器数据传输的 Server Actions,但我们的 React 理念是在所有平台和环境中提供相同的编程模型。如果可能的话,如果我们在客户端引入一项功能,我们的目标是使其也可以在服务器上运行,反之亦然。这一理念使我们能够创建一组 API,无论您的 App 在哪运行,它们都可以奏效,从而使以后能够更轻松地升级到不同的环境。
Actions 现已在 Canary 通道中提供,并将在 React 的下个版本中发布。
React Canary 新功能
我们引入了 React Canaries 作为一种选择,可以在设计接近最终版本后立即采用各个新型稳定功能,然后再以稳定的语义版本发布。
Canary 改变了我们开发 React 的方式。此前,功能会在 Meta 内部偷偷研发和构建,因此用户能且仅能在稳定版发布时才看到最终的打磨产品。对于 Canaries,我们正在社区的辅助下公开构建。这意味着,您会更快地了解新功能,因为此时它们正在锅里,而不是在它们新鲜出炉之后。
RSC(React 服务器组件)、资源加载、文档元数据和 Actions 都已登陆 React Canary,并且我们在 react.dev 上添加了这些功能的文档:
- 指令 :
"use client"
和"use server"
是专为全栈 React 框架设计的打包器功能。它们标记两个环境之间的"分割点":"use client"
表明打包器生成<script>
标签(比如 Astro Island),而"use server"
告诉打包器生成 POST 端点(比如 tRPC Mutations)。它们一起让我们可以编写可复用组件,这些组件将客户端交互与相关的服务器端逻辑组合在一起。 - 文档元数据 :我们添加了对在组件树中任意位置渲染
<title>
、<meta>
和元数据<link>
标签的内置支持。它们在所有环境中都殊途同归,包括完全客户端代码、SSR 和 RSC。这为 React Helmet 等库开创的功能提供了内置支持。 - 资源加载 :我们将
Suspense
与样式表、字体和脚本等资源的加载生命周期集成在一起,这样 React 会考虑它们来确定<style>
、<link>
等元素中的内容是否已加载和<script>
是否已准备好显示。我们还添加了新的资源加载 API,比如preload
和preinit
,更好地控制资源何时加载和初始化。 - Actions :我们添加了 Actions 来管理从客户端向服务器发送数据。我们可以将
action
添加到<form/>
等元素,使用useFormStatus
访问状态,使用useFormState
处理结果,并诉诸useOptimistic
积极更新 UI。
由于这些功能"梦幻联动",因此很难在稳定频道中单独发布它们。在没有访问表单状态的补充钩子的情况下,发布 Actions 会限制其实际可用性。在不集成 Server Action 的情况下引入 RSC 会使服务器上的数据修改变得复杂。
在我们向稳定渠道发布一组功能之前,我们需要确保它们能够协同工作,并且开发者拥有在生产中使用它们所需的一切。React Canaries 允许我们单独开发这些功能,并逐步发布稳定的 API,直到整个功能集完成。
React Canary 中当前的功能集已完成并准备发布。
React 19
经过几年的迭代,react@canary
现在已准备好交付给 react@latest
。上述新功能与您的 App 运行的任何环境兼容,提供生产使用所需的一切。由于资源加载和文档元数据对于某些 App 而言可能是一个重大变化,因此 React 的下个版本会是一个主要版本:React 19。
为发布做准备还有一大坨工作要做。在 React 19 中,我们还添加了长期要求的改进,这些改进需要重大更改,比如对 Web Components 的支持。我们现在的重点是落实这些更改,准备发布,最终确定新功能的文档,并发布所包含内容的公告。
在接下来的几个月中,我们会共享有关 React 19 包含的所有内容、如何采用新客户端功能,以及如何构建对 RSC 的支持的更多信息。
Offscreen(重命名为"Activity")
自上次更新以来,我们正在研究的一项功能从"Offscreen"重命名为"Activity"。"Offscreen"这个名称意味着,它仅适用于 App 中不可见的部分,但在研究该功能时,我们意识到 App 的某些部分可能是可见但未激活的,比如模态框后面的内容。新名称更准确地反映了将 App 的某些部分标记为"激活"或"失活"的行为。
Activity 仍在研发中,我们剩下的工作是最终确定向库开发者暴露的原语。我们已经取消了该领域的优先级,同时聚焦于更完整的交付功能。
本期话题是 ------ Server Action 可能让前后端不再分离,这是不是在"飚历史倒车"?
欢迎在本文下方群聊自由言论,文明共享。谢谢大家的点赞,掰掰~
《前端 9 点半》每日更新,坚持阅读,自律打卡,每天一次,进步一点。