React Canaries: メタ社外での段階的な機能ロールアウトの実現

2023年5月3日 Dan Abramov, Sophie Alpert, Rick Hanlon, Sebastian Markbåge, and Andrew Clark


メタ社内で長らく最先端のReactバージョンを利用してきたのと同様に、Reactコミュニティに対して、個々の新機能がデザイン的にほぼ完成した段階で、安定版リリース前に採用できるオプションを提供したいと考えています。公式にサポートされる新しいCanaryリリースチャネルを導入します。これにより、フレームワークなどの厳選された設定では、Reactのリリーススケジュールから個々のReact機能の採用を切り離すことができます。


要約:

  • Reactの公式にサポートされるCanaryリリースチャネルを導入します。公式にサポートされているため、リグレッションが発生した場合は、安定版リリースでのバグと同様に緊急度が高いものとして扱います。
  • Canaryを使用すると、セマンティックバージョニングで安定したリリースに組み込まれる前に、個々の新しいReact機能の使用を開始できます。
  • Experimentalチャネルとは異なり、React Canariesには採用の準備ができていると合理的に考えられる機能のみが含まれます。フレームワークで固定されたCanary Reactリリースをバンドルすることを推奨します。
  • Canaryリリースに組み込まれる際には、ブログで破壊的な変更と新機能をお知らせします。
  • これまでと同様に、Reactはすべての安定版リリースでセマンティックバージョニングに従います。

Reactの機能が通常どのように開発されるか

通常、すべてのReact機能は同じ段階を経ます。

  1. 初期バージョンを開発し、experimental_またはunstable_のプレフィックスを付けます。この機能は、experimentalリリースチャネルでのみ使用できます。この時点で、機能は大幅に変更されると予想されます。
  2. この機能をテストし、フィードバックを提供するのに協力してくれるメタのチームを見つけます。これにより、変更が加えられます。機能がより安定するにつれて、メタのより多くのチームと協力して試用します。
  3. 最終的に、デザインに自信を持てるようになります。API名からプレフィックスを削除し、ほとんどのメタ製品が使用するmainブランチでデフォルトで機能を使用できるようにします。この時点で、メタのどのチームでもこの機能を使用できます。
  4. 方向性に自信を深めるにつれて、新しい機能に関するRFCも投稿します。この時点で、デザインが幅広いケースに対応できることはわかっていますが、最後の最後に調整を加える可能性があります。
  5. オープンソースリリースを行う直前になったら、機能のドキュメントを作成し、最後に安定版のReactリリースで機能をリリースします。

このプレイブックは、これまでリリースしたほとんどの機能でうまく機能しています。ただし、機能が一般的に使用できる状態になったとき(ステップ3)と、オープンソースでリリースされるとき(ステップ5)の間には、大きなギャップが生じる可能性があります。

Reactコミュニティに対して、メタ社と同じアプローチに従い、Reactの次のリリースサイクルを待つ必要なく、個々の新機能をより早く(利用可能になり次第)採用できるオプションを提供したいと考えています。

これまでと同様に、すべてのReact機能は最終的に安定版リリースに組み込まれます。

マイナーリリースを増やすことはできないのか?

一般的に、新機能を導入するためにマイナーリリースを使用します。

ただし、これは常に可能とは限りません。新機能が、まだ完全に完了しておらず、積極的に反復処理を行っている他の新機能と相互接続されている場合があります。実装が関連しているため、それらを別々にリリースすることはできません。それらが同じパッケージ(たとえば、reactreact-dom)に影響を与えるため、それらを別々にバージョン管理することはできません。また、セマンティックバージョニングで要求されるような、メジャーバージョンのリリースを頻繁に行わずに、準備ができていない部分を反復処理する機能を維持する必要があります。

メタでは、mainブランチからReactをビルドし、毎週特定の固定コミットに手動で更新することで、この問題を解決しました。これは、React Nativeのリリースが過去数年間従ってきたアプローチでもあります。React Nativeのすべての安定リリースは、Reactリポジトリのmainブランチからの特定のコミットに固定されています。これにより、React Nativeは、グローバルなReactリリーススケジュールに縛られることなく、フレームワークレベルで重要なバグ修正を組み込み、新しいReact機能を段階的に採用できます。

このワークフローを他のフレームワークや厳選された設定でも利用できるようにしたいと考えています。たとえば、Reactのフレームワークでは、この破壊的な変更が安定版のReactリリースに組み込まれる前に、React関連の破壊的な変更を含めることができます。一部の破壊的な変更はフレームワークの統合にのみ影響するため、これは特に便利です。これにより、フレームワークはセマンティックバージョニングを破ることなく、独自のマイナーバージョンでそのような変更をリリースできます。

Canariesチャネルを使用したローリングリリースにより、フィードバックループを緊密化し、新機能がコミュニティで包括的にテストされるようにすることができます。このワークフローは、JavaScript標準委員会であるTC39が番号付きの段階で変更を処理する方法に近いです。新しいJavaScript機能が仕様の一部として正式に批准される前にブラウザに出荷されるのと同じように、新しいReact機能はReactの安定版リリースよりも前に、React上に構築されたフレームワークで利用できる場合があります。

なぜ実験的リリースではなく、実験的リリースを使うべきではないのでしょうか?

技術的には実験的リリースを使用することもできますが、実験的なAPIは安定化する過程で大幅な破壊的変更を受ける可能性があり(または完全に削除される可能性さえあります)、本番環境での使用はお勧めしません。カナリア版にも(他のリリースと同様に)間違いが含まれている可能性がありますが、今後は、ブログでカナリア版における重大な破壊的変更を発表する予定です。カナリア版は、Metaが内部で実行しているコードに最も近いものであるため、一般的に比較的安定していると期待できます。ただし、バージョンを固定し、ピン留めされたコミット間で更新する場合は、GitHubのコミットログを手動でスキャンする必要があります。

(フレームワークのような)キュレーションされた設定以外でReactを使用しているほとんどの人が、引き続き安定版リリースを使用することを希望すると考えています。 ただし、フレームワークを構築している場合は、特定のコミットに固定されたReactのカナリア版をバンドルし、自分のペースで更新することを検討してもよいでしょう。この利点は、React Nativeがここ数年行ってきたように、個々の完了したReactの機能とバグ修正をユーザー向けに、より早く、独自のリリーススケジュールで出荷できることです。欠点は、どのReactコミットがプルされているかを確認し、リリースに含まれるReactの変更をユーザーに伝える追加の責任を負うことです。

あなたがフレームワークの作成者で、このアプローチを試したい場合は、私たちにご連絡ください。

破壊的変更と新機能の早期発表

カナリア版リリースは、特定の時点で次の安定版Reactリリースに含まれるものの最良の推測を表しています。

従来は、リリースサイクルの最後(メジャーリリースを行う場合)にのみ破壊的変更を発表していました。カナリア版リリースがReactを消費する正式にサポートされた方法になったため、破壊的変更と重要な新機能をカナリア版に適用された時点で発表するようにシフトする予定です。たとえば、カナリア版でリリースされる破壊的変更をマージした場合は、必要な場合にコードモッドと移行手順を含め、Reactブログでそれに関する記事を書きます。次に、ピン留めされたReactカナリア版を更新してその変更を含めるメジャーリリースをカットするフレームワーク作成者は、リリースノートからブログ記事にリンクできます。最後に、安定したメジャーバージョンのReactの準備が整ったら、すでに公開されているブログ記事にリンクします。これにより、私たちのチームがより迅速に進歩できるようになることを願っています。

カナリア版に適用された時点でAPIをドキュメント化する予定です。これらのAPIがカナリア版以外ではまだ利用できない場合でも同様です。カナリア版でのみ利用可能なAPIは、対応するページに特別な注記でマークされます。これには、useのようなAPIや、その他いくつか(cachecreateServerContext など)が含まれます。これらについてはRFCを送信する予定です。

カナリア版はピン留めする必要があります

アプリやフレームワークにカナリア版のワークフローを採用する場合は、使用しているカナリア版の正確なバージョンを常にピン留めするようにしてください。カナリア版はプレリリースであるため、破壊的な変更が含まれている可能性があります。

例:React Server Components

3月に発表したように、React Server Componentsの規則は最終決定しており、ユーザー向けのAPI契約に関連する大幅な破壊的変更は予想されていません。ただし、アセットローディングなど、いくつかの絡み合ったフレームワーク専用の機能に取り組んでおり、そこでさらに破壊的な変更が予想されるため、Reactの安定版でReact Server Componentsのサポートをリリースすることはまだできません。

これは、React Server Componentsがフレームワークで採用される準備ができていることを意味します。ただし、次のReactメジャーリリースまでは、フレームワークがそれらを採用する唯一の方法は、ピン留めされたReactのカナリア版を出荷することです。(Reactの2つのコピーをバンドルすることを避けるために、これを希望するフレームワークは、reactreact-domをフレームワークに付属するピン留めされたカナリア版に強制的に解決させ、ユーザーにそれを説明する必要があります。例として、これはNext.js App Routerが行っていることです。)

安定版とカナリア版の両方に対するライブラリのテスト

禁止されるほど困難であるため、すべての単一のカナリア版リリースをテストすることをライブラリ作成者に期待していません。ただし、3年前にさまざまなReactプレリリースチャネルを初めて導入したときと同じように、ライブラリが最新の安定版と最新のカナリア版の両方に対してテストを実行することを推奨します。発表されていない動作の変化が見られた場合は、Reactリポジトリにバグを報告して、診断を支援できるようにしてください。この慣行が広く採用されるにつれて、新しいメジャーバージョンのReactにライブラリをアップグレードするために必要な労力が減ることを期待しています。これは、意図しないリグレッションが適用されると検出されるためです。

注意

厳密に言えば、カナリア版は新しいリリースチャネルではありません。以前はNextと呼ばれていました。ただし、Next.jsとの混同を避けるために、名前を変更することにしました。カナリア版がReactを使用する正式にサポートされた方法であるなど、新しい期待を伝えるために、新しいリリースチャネルとして発表します。

安定版リリースは以前と同じように機能します

安定版のReactリリースに変更は加えていません。