React Canary 版本:在 Meta 之外启用增量特性发布

2023年5月3日 作者:Dan AbramovSophie AlpertRick HanlonSebastian MarkbågeAndrew Clark


我们希望为 React 社区提供一个选项,以便在稳定版本发布之前,尽早采用单个新特性,前提是其设计已接近最终状态——这与 Meta 内部长期使用 React 最前沿版本的方式类似。我们正在引入一个新的官方支持的 Canary 发布渠道。它允许像框架这样的精选设置将单个 React 特性的采用与 React 发布计划解耦。


tl;dr

  • 我们正在为 React 引入一个官方支持的 Canary 发布渠道。由于它是官方支持的,如果出现任何回归问题,我们将以与稳定版本中的错误相同的紧迫性对待它们。
  • Canary 版本允许您在新的 React 特性进入语义版本控制稳定版本之前就开始使用它们。
  • 实验性 渠道不同,React Canary 版本只包含我们合理认为已准备好采用的特性。我们鼓励框架考虑捆绑固定版本的 Canary React 版本。
  • 当 Canary 版本中出现重大更改和新特性时,我们会通过博客公布。
  • 与以往一样,React 继续遵循语义版本控制 (semver) 的规范来发布每一个稳定版本。

React 特性的开发流程

通常,每个 React 特性都经历了相同的阶段

  1. 我们开发初始版本,并在其前面添加前缀 experimental_unstable_。该特性仅在 experimental 发布渠道中可用。在此阶段,该特性预计会发生重大更改。
  2. 我们会在 Meta 找到一个团队来帮助我们测试此特性,并提供反馈。这会导致一轮更改。随着特性的稳定性提高,我们会与 Meta 的更多团队合作来试用它。
  3. 最终,我们对设计充满信心。我们从 API 名称中删除前缀,并默认情况下在 main 分支上启用该特性,大多数 Meta 产品都使用该分支。此时,Meta 的任何团队都可以使用此特性。
  4. 随着我们对方向的信心增强,我们还会发布新特性的 RFC。此时,我们知道该设计适用于广泛的情况,但我们可能会进行一些最后的调整。
  5. 当我们接近发布开源版本时,我们会为该特性编写文档,并最终在稳定的 React 版本中发布该特性。

此流程对我们迄今为止发布的大多数特性都非常有效。但是,特性普遍可以使用(步骤 3)与在开源中发布(步骤 5)之间可能存在显著的时间差。

我们希望为 React 社区提供一个选项,以便遵循与 Meta 相同的方法,尽早采用单个新特性(一旦可用),而无需等待下一个 React 发布周期。

与以往一样,所有 React 特性最终都会进入稳定版本。

我们能否只进行更多小版本发布?

通常,我们确实使用小版本发布来引入新特性。

但是,这并非总是可行。有时,新特性与尚未完全完成且我们仍在积极迭代的*其他*新特性相互关联。我们无法分别发布它们,因为它们的实现是相关的。我们无法分别对它们进行版本控制,因为它们会影响相同的包(例如,reactreact-dom)。我们需要保持在不进行大量主要版本发布(语义版本控制需要我们这样做)的情况下迭代未准备好部分的能力。

在 Meta,我们通过从 main 分支构建 React,并每周手动将其更新到特定的固定提交来解决这个问题。这也是 React Native 在过去几年中一直遵循的方法。React Native 的每个*稳定*版本都固定在 React 代码库的 main 分支中的特定提交上。这允许 React Native 包含重要的错误修复,并在框架级别增量地采用新的 React 特性,而无需与全局 React 发布计划耦合。

我们希望将此工作流程提供给其他框架和精选的设置。例如,它允许一个基于React的框架在破坏性更改包含到稳定的React版本之前包含一个与React相关的破坏性更改。这尤其有用,因为某些破坏性更改只会影响框架集成。这允许框架在其自己的次要版本中发布此类更改,而不会破坏语义版本控制。

使用Canary通道的滚动发布将使我们能够拥有更紧密的反馈循环,并确保新功能在社区中得到全面的测试。此工作流程更接近于JavaScript标准委员会TC39 处理分阶段更改的方式。新的React功能可能在基于React的框架中可用,然后才在稳定的React版本中可用,就像新的JavaScript功能在浏览器中发布然后才正式批准为规范的一部分一样。

为什么不使用实验性版本?

虽然您可以在技术上使用 实验性版本,但我们建议不要在生产环境中使用它们,因为实验性API在稳定化的过程中可能会发生重大破坏性更改(甚至可能被完全删除)。虽然Canary版本也可能包含错误(与任何版本一样),但展望未来,我们计划在我们的博客上宣布Canary版本中的任何重大破坏性更改。Canary版本最接近Meta内部运行的代码,因此您通常可以预期它们相对稳定。但是,您需要固定版本并在更新已固定提交之间的内容时手动扫描GitHub提交日志。

我们预计大多数在精选设置(如框架)之外使用React的人将希望继续使用稳定版本。但是,如果您正在构建框架,您可能需要考虑捆绑固定到特定提交的Canary版本的React,并按照您自己的节奏更新它。这样做的好处是,您可以为您的用户更早地发布单独完成的React功能和错误修复,并按照您自己的发布计划进行,这与React Native过去几年一直在做的事情类似。缺点是您需要承担额外的责任来审查正在引入哪些React提交,并向您的用户传达您的版本中包含哪些React更改。

如果您是框架作者并想尝试这种方法,请联系我们。

提前宣布破坏性更改和新功能

Canary版本代表我们对任何给定时间将包含到下一个稳定React版本中的内容的最佳猜测。

传统上,我们只在发布周期结束时(进行主要版本发布时)宣布破坏性更改。现在Canary版本已成为正式支持的React使用方式,我们计划转向在Canary版本中落地时宣布破坏性更改和重要的新功能。例如,如果我们合并了一个将包含在Canary版本中的破坏性更改,我们将在React博客上撰写一篇关于它的文章,如果需要,还包括代码修改和迁移说明。然后,如果您是框架作者,正在发布更新已固定的React Canary版本以包含该更改的主要版本,您可以从您的发行说明中链接到我们的博客文章。最后,当React的稳定主要版本准备就绪时,我们将链接到那些已经发布的博客文章,我们希望这将帮助我们的团队更快地取得进展。

我们计划在Canary版本中记录API——即使这些API在Canary版本之外尚不可用。仅在Canary版本中可用的API将在相应的页面上标有特殊说明。这将包括像 use 之类的API,以及其他一些API(例如 cachecreateServerContext),我们将为此发送RFC。

必须固定Canary版本

如果您决定为您的应用程序或框架采用Canary工作流程,请确保始终固定您正在使用的Canary的确切版本。由于Canary版本是预发布版本,它们可能仍然包含破坏性更改。

示例:React服务器组件

正如我们在三月份宣布的那样,React服务器组件约定已经最终确定,我们预计不会出现与其用户界面API契约相关的重大破坏性更改。但是,我们还不能在稳定的React版本中发布对React服务器组件的支持,因为我们仍在处理几个相互关联的仅限框架的功能(例如 资源加载),并预计在那里会有更多破坏性更改。

这意味着React服务器组件已准备好被框架采用。但是,在下一个主要React版本发布之前,框架采用它们的唯一方法是发布一个固定的Canary版本的React。(为了避免捆绑两个React副本,希望这样做 的框架需要强制解析 reactreact-dom 到他们与他们的框架一起发布的固定的Canary版本,并向他们的用户解释这一点。例如,这就是Next.js App Router所做的。)

针对稳定版和Canary版本测试库

我们不希望库作者测试每个Canary版本,因为这将非常困难。但是,正如我们 三年前最初引入不同的React预发布渠道时一样,我们鼓励库针对最新的稳定版本和最新的Canary版本运行测试。如果您看到未宣布的行为变化,请在React存储库中提交错误,以便我们可以帮助诊断它。我们预计,随着这种实践的广泛采用,升级库到新的主要React版本所需的工作量将减少,因为意外的回归将在它们落地时被发现。

注意

严格来说,Canary并非一个新的发布渠道——它过去被称为Next。但是,我们决定将其重命名为避免与Next.js混淆。我们将它宣布为一个新的发布渠道是为了传达新的期望,例如Canary成为正式支持的React使用方式。

稳定版本的工作方式与之前相同

我们没有对稳定的 React 版本进行任何更改。