本日、CloudflareはVercel、Shopify、およびNode.jsとDenoの両方の中心的な個々のコントリビューターと協力して、Webブラウザではない、JavaScriptベース開発環境で標準化Web APIを相互運用できる実装に焦点を当てた、新しいコミュニティグループの設立を発表いたします。
W3CおよびWeb Hypertext Application Technology Working Group(WHATWG)は、開発環境としての標準化APIとWebの機能を、長い間先頭に立って開発してきました。fetch()、ReadableStreamおよび WritableStream、URL、URLPattern、TextEncoder などのAPIは、現代のWeb開発における馴染みの、そして貴重なコンポーネントになりました。ただし、これら既存グループは常にWebブラウザの特定のニーズのみを考慮するよう用途が明白に制限されてきたため、Webブラウザとは少し異なる任意の環境で開発標準を最適化することは容易ではありませんでした。この影響の好例としてStreams標準の一部の非ブラウザ実装が、主に標準のAPIがどのように指定されているかによって、同等のNode.jsストリームおよびDenoリーダーの実装と比べると速度が1桁低下することが挙げられます。
Cloudflare Workersのようなサーバーレス環境、あるいはNode.jsやDenoのようなランタイムには、単にウェブブラウザと関連しない、および関連する、幅広い要件、問題、懸念が存在します。この食い違いのため、そしてさまざまな仕様の開発中にこれらの違いが明確に考慮されなかったため、実際には複数の環境で共通する機能に対し、非ブラウザのランタイムに独自の非標準ソリューションが実装される事態が生じてきました。
この新しい取り組みでは、スタック全体のあらゆる場所でデプロイされた、_すべての_Web環境に共通の要件について議論および推奨する場を提供することで、この状況を変えようとしています。
開発者にとってのメリットは?
開発者は自分のコードが移植可能であることを望んでいます。一度書いたコードを別の環境(例えばNode.jsからDenoへ)に移植する場合、今までと全く同じ動作をさせるために完全に_書き換える_ことは望みません。
Cloudflareユーザからよく受ける質問の1つに、npmで公開されている、Node.js固有のAPIやDeno固有のAPIのセットを利用する任意のモジュールを使用するにはどうすればよいかというものがあります。通常その答えには任意の組み合わせのpolyfill実装を引用することが含まれます。この状況はDenoプロジェクトでも同様で、完全なNode.jsのコアAPIのpolyfillを直接標準ライブラリに統合することが選択されてきました。これらの環境で同様の共通標準が実装されればされるほど、開発者エコシステムは、どこで実行されるとしても動作するよう記述されたコードに依存できるようになります。
Cloudflare Workers、Node.js、Deno、Webブラウザはそれぞれ全く異なるものですが、共通する機能もかなり多くあります。例えば、これらすべては暗号ハッシュを生成するためのAPIを提供し、ストリーミングデータを何らかの方法で扱い、どこかにHTTPリクエストを送信するための機能を提供します。このような重複があり、要件と機能が同じである場合、環境はすべて同じ標準化されたメカニズムを実装する必要があります。
ウェブ相互運用可能ランタイムコミュニティグループ
新しいWeb相互運用可能ランタイムコミュニティグループ(または「WinterCG」)は、W3Cの確立したプロセスの下で運営されています。
このグループの名前は、このグループが達成しようとしている(または_しない_)目標を理解するために重要であるため、名前をつけるまで時間を要しました。重要なのは「Web相互運用可能」というフレーズです。
私たちは「Web」をW3CやWHATWGコミュニティが使っているのとまったく同じ意味(正確には_Webブラウザ_)で使用しています。「Web相互運用可能」という用語は、その機能がWebブラウザで実装されている方法と_同一または少なくとも可能な限り一致する_方法で実装されることを意味します。例えば、new URL()コンストラクタがブラウザで動作する方法は、new URL()コンストラクタがNode.js、Deno、Cloudflare Workersで動作すべき方法と全く同じである必要があります。
ただし、Node.js、Deno、Cloudflare Workers は明らかにWebブラウザではないという事実を認識することは重要です。この点を明白にすべきであることに加え、様々なJavaScript環境間の違いが標準化APIの設計上の決定に大きく影響することに注意することは重要です。例えば、Node.jsとDenoはそれぞれローカルファイルシステムへのフルアクセスが可能です。一方、Cloudflare Workersはローカルファイルシステムを持たず、Webブラウザは必然的にアプリケーションによるローカルファイルシステムの操作を制限します。同様に、Webブラウザは本来Webサイトの「オリジン」の概念を含んでおり、様々なセキュリティ脅威からユーザーを保護するために CORS のようなメカニズムを実装しますが、Node.js、Deno、Cloudflare Workersが動作するサーバー側には「オリジン」と同等の概念は存在しません。
これまで、W3CとWHATWGはWebブラウザのニーズにのみ関わってきました。新しいWeb相互運用可能ランタイムコミュニティグループは、それ以外の人のニーズを明確に取り上げ提唱しています。
これは、WinterCGが独立して、独自の標準APIセットを公開することを意図しているわけではありません。WinterCGから生まれる新しい仕様のアイデアは、まずW3CとWHATWGの既存のワークストリームで検討され、できるだけ幅広い意見の一致を得ることを目指します。ただし、他の環境(Cloudflare Workersなど)で必要な機能をWebブラウザでは特に必要でない、あるいは無関係であることが明らかになった場合、WinterCGは独自の仕様を進めることができます。この仕様には確立されたWeb標準と意図的に衝突したり互換性がないものは導入しないという制約が課せられます。
WinterCGには誰でも参加できます。確立されたW3Cのプロセスとポリシーの下で運営され、すべての作業は「wintercg」GitHub組織を通じてオープンにアクセスでき、そのすべては相互運用性の最大化という目標が中心に据えられています。
取り組み中
WinterCGはすでに多くの重要な作業項目に着手しています。
最小限の共通Web API
現在の仕様書の草稿 の序論から:
「最小限の共通WebプラットフォームAPIは、ブラウザおよび非ブラウザのJavaScriptベースのランタイム環境に共通する機能の最小セットを定義することを目的とした、標準化WebプラットフォームAPIの厳選されたサブセットです。」
あるいは別の言い方をすれば、_既存の_Web APIの最小セットで、Node.js、Deno、Cloudflare Workersに一貫して適切に実装されるものです。大半のAPIは、いくつかの例外や微妙な差異を除くと、すでにこれらの環境内に存在しているため、残された作業の大部分は、これらの実装が相対的な仕様と一致しており、環境間で移植可能であるようにすることです。
以下の表には、現在このサブセットに含まれているすべてのAPIが一覧されています(そのAPIが現在Node.js、Deno、Cloudflare Workersでサポートされているか、または近いうちにサポートされる可能性があるかを同時に示しています)。
Node.js
Deno
Cloudflare Workers
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
ReadableStreamDefaultController
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
(間もなく)
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
TransformStreamDefaultController
✔️
✔️
(間もなく)
✔️
✔️
✔️
?
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
WritableStreamDefaultController
✔️
✔️
✔️
globalThis.self
?
✔️
(間もなく)
globalThis.atob()
✔️
✔️
✔️
globalThis.btoa()
✔️
✔️
✔️
globalThis.console
✔️
✔️
✔️
globalThis.crypto
✔️
✔️
✔️
globalThis.navigator.userAgent
?
✔️
✔️
globalThis.queueMicrotask()
✔️
✔️
✔️
globalThis.setTimeout() / globalthis.clearTimeout()
✔️
✔️
✔️
globalThis.setInterval() / globalThis.clearInterval()
✔️
✔️
✔️
globalThis.structuredClone()
✔️
✔️
✔️
いずれかの環境が標準化APIの定義と異なる場合(例えば、setTimeout()およびsetInterval()のNode.js実装)、その違いを説明した明確な文書が用意されます。このような差異は既存コードとの後方互換性のためにのみ存在する必要があります。
Web Cryptography Streams
Web Cryptography APIは、一般的な暗号化操作用に最小限の(そして非常に_限定的な_)APIを提供します。主要な制限の1つは、Node.jsの組み込みcryptoモジュールとは異なり、ストリーミング入出力をサポートしていないことです。Web Cryptographyのすべての機能は、メモリ上にあるデータのチャンクで一度に動作します。このため、暗号化操作のパフォーマンスと拡張性が厳しく制限されます。Webブラウザ以外の環境でこれらのAPIを使用し、うまく動作させようとすると、大変骨の折れる作業になります。
この問題に対処するため、WinterCGはWeb Crypto Streamsの新しい仕様の起草を開始しました。これはWeb Cryptographyの仕様を更新するために現在W3Cが独自に行っている大きな取り組みの一部として、検討用にW3Cに送信される予定です。目標は、既存の標準に準拠した方法で、Webブラウザを含む、Web全体にストリーミング暗号処理を導入することです。
サーバ用fetch()のサブセット
最近リリースされたバージョン18.0.0で、Node.jsはWHATWG標準fetch()API の実装を提供するJavaScript環境の集合に加わりました。ただし、Node.js、Deno、Cloudflare Workersでfetch()を実装する方法とWebブラウザで実装する方法には、重要な違いがいくつもあります。
ひとつには、サーバー環境にはWebブラウザのような「オリジン」という概念がないことが挙げられます。クロスサイトスクリプティングの脆弱性から保護することを目的としたCORSのような機能は、サーバー上では全く意味がありません。同様に、Webブラウザは一般には1人のユーザーによって使用され、グローバルにスコープされたCookieストアの概念を持っているのに対し、サーバーおよびサーバーレスアプリケーションは同時に数百万のユーザーによって使用され、セッションと認証の詳細を潜在的に含むグローバルにスコープされたCookieストアは非現実的かつ危険である可能性があります。
環境の違いが深刻であるため、fetch標準の変更案について推論し、合意を得ることはたいてい困難です。例えば、提案された新しいAPIは、サーバー上でfetchを使用する場合は非常に適切であっても、Webブラウザでfetchを使用する場合は全く役に立たない可能性があります。ブラウザに関連するセキュリティの懸念は、サーバーには全く影響を与えない場合があります。
この問題に対処し、Webブラウザ以外の環境でも一貫した方法でfetchを実装しやすくするために、WinterCGは特にこれらの異なる要件および制約を扱うfetch標準のサブセットを文書化する作業を行っています。
このサブセットではfetch標準との完全な互換性を得られるようになるよう、Node.js、Deno、Cloudflare Workersでfetchに取り組んできたメンバーの協力により開発されます。これは、fetch標準の定義と競合することは意図するものではなく、むしろ、これらの他の環境でfetchを適切に実装する方法を示す、文書化された一連のガイドラインとなることを目的としています。
まだ始まったばかり
Web相互運用可能ランタイムコミュニティグループはまだ始まったばかりですが、多くの野心的な目標を持っています。誰でも参加でき、すべての作業がGitHubのhttps://github.com/wintercgを介してオープンに行われます。Web機能が利用可能で、一貫して動作し、スタックを超えてどこでも動作するすべてのWeb開発者の要求に応えるようにするため、W3C、WHATWG、および一般的なJavaScriptコミュニティとの協力を積極的に求めています。
WinterCGの詳細については、https://wintercg.orgを参照してください。参加方法の詳細については、https://github.com/wintercg/adminを参照してください。