React Canary: Meta 外での段階的な新機能導入

May 3, 2023 by Dan Abramov, Sophie Alpert, Rick Hanlon, Sebastian Markbåge, and Andrew Clark


私たちは、安定版がリリースされる前に、個々の新機能の設計がほぼ確定した段階でそれらを採用できるという選択肢を、React コミュニティに提供したいと考えています。これは、Meta が長年、React の最先端バージョンを社内で使用してきたやり方に似ています。私たちは、新たに公式サポート対象となる Canary リリースチャンネルを導入します。これにより、フレームワークのような統合済セットアップが、個々の React 機能の採用を React のリリーススケジュールから切り離して行えるようになります。


tl;dr

  • React は公式にサポートされる Canary リリースチャンネルを導入します。公式にサポートされているため、何らかのリグレッションが発生した場合、安定版リリースのバグと同様の緊急度で対応します。
  • Canary により、semver に従う安定版リリースに達する前に、個々の新しい React 機能を使用し始めることができます。
  • Experimental チャンネルとは異なり、React Canary には、採用準備が整っていると合理的に判断できる機能のみが含まれます。フレームワークは Canary React のリリースをバージョン固定した上でバンドルするよう検討することをお勧めします。
  • Canary リリースでリリースした後に発生した破壊的変更や新機能は、ブログで告知を行います。
  • これまで通り、React はすべての安定版リリースにおいて semver に従います。

通常の React 機能の開発方法

通常、React のすべての機能は以下のような段階を経て開発されています。

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

この戦略はこれまでにリリースしてきたほとんどの機能に対してはうまく機能します。ただし、機能が概ね利用可能になること(ステップ 3)とオープンソースでリリースされる(ステップ 5)こととの間には、大きなギャップがあることがあります。

私たちは React コミュニティに、Meta と同じアプローチで、個々の新機能が利用可能になった段階でそれらを早期に採用し、React の次のリリースサイクルまで待たないで済む、というオプションを提供したいと考えています

これまで通り、すべての React の機能は最終的には安定板のリリースに含まれることになります。

ただマイナーリリースを増やせばいいのでは?

一般論として、現に私たちは新機能の導入に対してはマイナーリリースを使用することにしています。

しかしこれが常に可能なわけではありません。場合によってはその新機能が、まだ完全に完成しておらず活発に研究中のほかの新機能と相互に関連していることがあります。実装が関連しているため、別々にリリースすることはできません。同じパッケージ(例えば reactreact-dom)に影響するものなので、バージョン番号を分けることもできません。そして、semver の要求通りにやってメジャーバージョンリリースを乱発してしまうということなしに、準備が整っていない機能を頻繁に書き換えられるようにする必要もあります。

Meta では、main ブランチから React をビルドし、毎週特定のピン留めされたコミットに手動で更新することによって、この問題を解決しています。これはまた、過去数年間にわたって React Native リリースが実施してきたアプローチでもあります。React Native のすべての安定版リリースは、React リポジトリの main ブランチの特定のコミットにピン留めされています。これにより、React Native は重要なバグ修正を取り込むことができ、フレームワークレベルで新しい React 機能を段階的に採用し、グローバルな React のリリース予定に依存しないようにできます。

このワークフローを、他のフレームワークや統合済セットアップでも利用可能にしたいと考えているのです。例えば、これにより、React の上に作られているフレームワークが、React 関連の破壊的変更を、それが安定版リリース入る前に取り込むことができます。これが特に有用なのは、一部の破壊的変更はフレームワークとの結合部分にのみ影響するものだからです。これによりフレームワークは semver ルールを破ることなく、そのような破壊的変更を独自にマイナーバージョンを付けてリリースできます。

Canary チャンネルでの継続的リリースにより、より緊密なフィードバックループを実現し、新機能がコミュニティで包括的な検証を確実に受けられるようにすることができます。このワークフローは、JavaScript の標準化委員会である TC39 が番号付きのステージで変更を処理する方法に近いものです。新しい React 機能は、React の安定版でリリースされる前に、React をベースにしたフレームワークにおいて先に利用可能になることがあります。これは、新しい JavaScript 機能が、仕様の公式な一部として批准されるより前に、先にブラウザで利用可能になることと同様です。

なぜ Experimental リリースを使わないのか?

技術的には Experimental リリースを使うことは可能ですが、実験的な API は、安定化への道のりの途中でで大幅な変更が行われる(または完全に削除される)ことがあるため、実験的リリースを本番環境で使用することはお勧めしません。Canary リリースにも(どんなリリースでもそうであるように)誤りが含まれることはありますが、今後はこのブログで Canary における破壊的変更を告知する予定です。Canary は、Meta が社内で実行しているコードに最も近いため、一般的には比較的安定していると考えられます。ただし、バージョンを固定して、ピン留めされたコミットを変更する際には手作業で GitHub のコミットログを確認する必要があります。

React を統合済セットアップ(フレームワークなど)以外で使用しているほとんどの人々は、Stable リリースを引き続き使用することになると考えています。ただし、フレームワークを開発している場合は、特定のコミットにピン留めされた React の Canary バージョンをバンドルし、自分のペースで固定バージョンを更新していくことを検討してください。これによる利点は、過去数年間 React Native で行われてきたことと同様に、完成された個々の React 機能やバグ修正をユーザに対して早期に、かつ自身のリリーススケジュールに基づいて提供できるようになることです。デメリットとしては、取り込まれる React のコミットを自身で確認し、リリースに含まれる React の変更に対してユーザに伝えるための追加の責任が生じるということです。

もしあなたがフレームワークの作者であり、このアプローチを試してみたいと思っている場合は、我々にお問い合わせください。

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

Canary リリースは、その時点で我々が次の安定版 React リリースに入ると予想しているものをもっともよく反映しています。

従来は、リリースサイクルの終盤、つまりメジャーリリースの際に、破壊的変更について告知していました。しかし、Canary リリースが React の公式にサポートされる使用方法となったため、破壊的変更や重要な新機能は Canary でのリリース時に順次発表する方向に移行する予定です。たとえば、Canary で破壊的変更がマージされる場合、React ブログにそれに関する投稿を行い、必要に応じて codemod や移行手順も含めます。これにより、フレームワークの作者が当該変更を含むよう React Canary の固定バージョンを更新してメジャーリリースを切り出す場合、リリースノートから React ブログの投稿にリンクすることができます。最後に、React の安定版メジャーバージョンが準備できた時点で、私たちはすでに公開されているブログ投稿へのリンクを貼るようになります。これにより、私たちのチームがより迅速に先に進めるようになることを期待しています。

API の文書化についても、Canary に登場する時点で行われる計画です。これらの API が Canary 外では利用できない場合でもです。Canary でのみ利用可能な API は、該当するページで特別な注釈によりマークされます。これには、use のような API や、cachecreateServerContext のようなこれから RFC を作成する予定の API が含まれます。

Canary のバージョンを固定する

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

例:React Server Components

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

これは、React Server Components はフレームワークによって採用される準備が整っていることを意味します。ただし、次のメジャー React リリースまで、フレームワークがそれらを採用する唯一の方法は、ピン止めされた React の Canary 版と併せてリリースすることです。(React の 2 つのコピーをバンドルしてしまうのを避けるため、これを行いたいフレームワークは、reactreact-dom がフレームワークとともにリリースされたバージョン固定済みの Canary に解決 (resolve) されるよう強制し、それをユーザに説明する必要があります。例えば Next.js の App Router はこれを行っています。)

安定版と Canary 版の両方に対してライブラリをテストする

ライブラリ作者がすべての Canary リリースをテストすることは期待していません。それは非常に困難でしょう。ただし、3 年前に複数の React プレリリースチャンネルを初めて導入したときと同様に、ライブラリは、最新の安定バージョンと最新の Canary バージョンの両方に対してテストを実行することをお勧めします。発表されなていない振る舞いの変化が見られた場合、React リポジトリにバグを登録して、調査の手助けができるようにしてください。この慣行が広く採用されるにつれ、React の新しいメジャーバージョンにライブラリがアップグレードする際に必要な労力が減少すると予想されます。なぜなら、偶発的なリグレッションが発生したときにリリース直後に見つけることができようになるからです。

補足

厳密に言えば、Canary は新しいリリースチャンネルではありません。これは以前 Next と呼ばれていたものです。ただし、Next.js との混乱を避けるため、名前を変更することにしました。これを新しいリリースチャンネルという形で発表しているのは、新しく期待できること、つまり Canary が公式にサポートされる React の使用方法であるということなどについてお伝えするためです。

安定版リリースはこれまで同様

安定版 React のリリース方針に関しては何の変更も行いません。