React 实验室:2022 年 6 月进展

2022 年 6 月 15 日,Andrew ClarkDan AbramovJan KassensJoseph SavonaJosh StoryLauren TanLuna RuanMengdi ChenRick HanlonRobert ZhangSathya GunasekaranSebastian MarkbågeXuan Huang 联合撰写


React 18 历经数年打磨,为 React 团队带来了宝贵的经验教训。它的发布是多年研究和探索许多路径的结果。其中一些路径取得了成功;还有更多的是死胡同,但带来了新的见解。我们吸取的一个教训是,如果社区在不了解我们正在探索的这些路径的情况下等待新功能,那将是令人沮丧的。


我们通常会有多个项目在同时进行中,从更具实验性的到明确定义的都有。展望未来,我们希望开始定期与社区分享更多关于我们在这些项目中的工作进展。

需要说明的是,这不是一个有明确时间线的路线图。其中许多项目都处于积极研究阶段,因此难以确定具体的发布时间。根据我们的学习情况,它们甚至可能永远不会以当前的迭代形式发布。相反,我们希望与您分享我们正在积极思考的问题空间,以及我们迄今为止的收获。

服务器组件

我们在 2020 年 12 月宣布了 React 服务器组件 (RSC) 的实验性演示。从那时起,我们一直在完善它在 React 18 中的依赖关系,并根据实验反馈进行更改。

特别是,我们放弃了使用分叉 I/O 库(例如 react-fetch)的想法,而是采用 async/await 模型以获得更好的兼容性。从技术上讲,这并不会阻止 RSC 的发布,因为您也可以使用路由器进行数据获取。另一个变化是我们正在放弃文件扩展名方法,而转向 注释边界

我们正在与 Vercel 和 Shopify 合作,以统一 Webpack 和 Vite 中共享语义的打包器支持。在发布之前,我们希望确保 RSC 的语义在整个 React 生态系统中都是一致的。这是实现稳定的主要障碍。

资源加载

目前,脚本、外部样式、字体和图像等资源通常使用外部系统进行预加载和加载。这可能会使跨流式传输、服务器组件等新环境的协调变得棘手。我们正在考虑添加 API,以通过在所有 React 环境中都能正常工作的 React API 预加载和加载去重的外部资源。

我们还在考虑让这些 API 支持 Suspense,以便您可以拥有在加载之前阻止显示但不会阻止流式传输和并发渲染的图像、CSS 和字体。这可以帮助避免视觉元素弹出和布局变化时出现 “爆米花” 现象。

静态服务器渲染优化

静态站点生成 (SSG) 和增量静态再生 (ISR) 是提高可缓存页面性能的好方法,但我们认为我们可以添加一些功能来提高动态服务器端渲染 (SSR) 的性能——尤其是在大多数但并非所有内容都是可缓存的情况下。我们正在探索利用编译和静态传递来优化服务器渲染的方法。

React 优化编译器

我们在 2021 年 React Conf 上 提前预览 了 React Forget。它是一个编译器,可以自动生成 useMemouseCallback 调用的等效项,以最大程度地降低重新渲染的成本,同时保留 React 的编程模型。

最近,我们完成了编译器的重写,使其更加可靠和强大。这种新架构允许我们分析和记忆更复杂的模式,例如使用局部突变,并开启了许多新的编译时优化机会,而不仅仅是与记忆化 Hooks 相提并论。

我们还致力于构建一个用于探索编译器各个方面的游乐场。虽然游乐场的目标是使编译器的开发更容易,但我们认为它将使尝试和构建对编译器功能的直观感受变得更容易。它揭示了其内部工作原理的各种见解,并在您键入时实时呈现编译器的输出。这将在编译器发布时一起发布。

屏幕外

如今,如果您想隐藏和显示组件,您有两个选择。一种是将其完全从树中添加或删除。这种方法的问题是,每次卸载时都会丢失 UI 的状态,包括存储在 DOM 中的状态,例如滚动位置。

另一种选择是保持组件处于挂载状态,并使用 CSS 在视觉上切换外观。这会保留 UI 的状态,但会增加性能成本,因为 React 必须在每次收到新更新时都渲染隐藏的组件及其所有子组件。

Offscreen 引入了第三种选择:在视觉上隐藏 UI,但降低其内容的优先级。这个想法在精神上类似于 content-visibility CSS 属性:当内容隐藏时,它不需要与 UI 的其余部分保持同步。React 可以将渲染工作推迟到应用程序的其余部分空闲,或者直到内容再次变为可见。

Offscreen 是一种低级功能,可以解锁高级功能。与 React 的其他并发功能(如 startTransition)类似,在大多数情况下,您不会直接与 Offscreen API 交互,而是通过固执己见的框架来实现以下模式:

  • 即时转换。 一些路由框架已经预取数据以加速后续导航,例如悬停在链接上时。借助 Offscreen,他们还可以预渲染后台中的下一个屏幕。
  • 可重用状态。 同样,在路由或选项卡之间导航时,您可以使用 Offscreen 保留上一个屏幕的状态,以便您可以切换回来并从上次中断的地方继续。
  • 虚拟化列表渲染。 显示大量项目时,虚拟化列表框架将预渲染比当前可见的更多行。您可以使用 Offscreen 以比列表中可见项目更低的优先级预渲染隐藏行。
  • 背景内容。 我们还在探索一项相关功能,用于在不隐藏内容的情况下降低其在后台的优先级,例如在显示模态覆盖层时。

过渡跟踪

目前,React 有两个分析工具。原始分析器 显示了分析会话中所有提交的概览。对于每次提交,它还显示了所有渲染的组件以及它们渲染所需的时间。我们还有一个在 React 18 中引入的时间轴分析器的测试版,它显示了组件何时安排更新以及 React 何时处理这些更新。这两个分析器都可以帮助开发人员识别代码中的性能问题。

我们意识到,开发人员发现了解单个缓慢提交或组件在上下文之外并没有那么有用。了解是什么导致了缓慢的提交更有用。开发人员希望能够跟踪特定的交互(例如按钮单击、初始加载或页面导航),以观察性能回归并了解交互速度缓慢的原因以及如何解决它。

我们之前尝试通过创建一个交互跟踪 API 来解决这个问题,但它存在一些根本的设计缺陷,这些缺陷降低了跟踪交互速度缓慢的原因的准确性,有时会导致交互永远不会结束。由于这些问题,我们最终删除了此 API

我们正在开发新版本的交互跟踪 API(暂定名为 Transition Tracing,因为它通过 startTransition 启动),以解决这些问题。

新的 React 文档

去年,我们发布了新 React 文档网站 (后来作为 react.dev 发布) 的测试版。新的学习材料首先教授 Hooks,并包含新的图表、插图以及许多交互式示例和挑战。我们暂停了这项工作,专注于 React 18 的发布,但现在 React 18 已经发布,我们正在积极努力完成和发布新的文档。

我们目前正在编写有关效果的详细部分,因为我们听说这对 React 新用户和经验丰富的用户来说都是比较具有挑战性的主题。使用效果进行同步 是本系列中第一个发布的页面,接下来的几周还会有更多内容。当我们第一次开始编写关于效果的详细部分时,我们意识到可以通过向 React 添加新的原语来简化许多常见的效果模式。我们已经在useEvent RFC 中分享了关于这一点的一些初步想法。它目前处于早期研究阶段,我们仍在迭代这个想法。我们感谢社区迄今为止对 RFC 的评论,以及对正在进行的文档重写的反馈和贡献。我们要特别感谢Harish Kumar 提交和审查了对新网站实现的许多改进。

感谢Sophie Alpert 审阅这篇博客文章!