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 预加载和加载去重后的外部资源。

我们还在考虑让这些支持 Suspense,这样您就可以拥有在加载前阻止显示但不会阻止流式处理和并发渲染的图像、CSS 和字体。这有助于避免“爆米花效应”,即视觉效果突然出现和布局发生变化。

静态服务器渲染优化

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

React 优化编译器

我们在 2021 年 React Conf 上对 React Forget 做了 早期预览。这是一个编译器,它会自动生成等效于 useMemouseCallback 调用的代码,以最大限度地减少重新渲染的成本,同时保留 React 的编程模型。

最近,我们完成了编译器的重写工作,使其更加可靠和强大。这种新的架构使我们能够分析和记忆化更复杂的模式,例如 局部变异 的使用,并打开了超越与记忆化 Hook 同等水平的许多新的编译时优化机会。

我们还在开发一个用于探索编译器许多方面的游乐场。虽然游乐场的目标是使编译器的开发更容易,但我们认为它将使试用它并建立对编译器功能的直觉更容易。它揭示了编译器内部工作原理的各种见解,并在您键入时实时渲染编译器的输出。这将在编译器发布时与编译器一起发布。

屏幕外

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

另一种选择是保持组件挂载并使用 CSS 在视觉上切换外观。这保留了 UI 的状态,但它会带来性能成本,因为无论何时收到新的更新,React 都必须继续渲染隐藏的组件及其所有子组件。

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

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

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

转换跟踪

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

我们意识到,开发人员不会发现脱离上下文了解单个缓慢的提交或组件有用。了解实际导致缓慢提交的原因更有用。而且开发人员希望能够跟踪特定的交互(例如单击按钮、初始加载或页面导航)以监视性能下降,并了解交互缓慢的原因以及如何修复它。

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

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

新的 React 文档

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

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

感谢Sophie Alpert审核这篇博文!