A Community Group for Web-interoperable JavaScript runtimes

Aujourd'hui, Cloudflare, en partenariat avec Vercel, Shopify et les principaux contributeurs individuels de Node.js et Deno , annonce la création d'un nouveau groupe communautaire    axé sur la mise en œuvre interopérable d'API Web normalisées dans des environnements de développement JavaScript autres que les navigateurs Web.

Le W3C et le Web Hypertext Application Technology Working Group (ou WHATWG) ont longtemps été les pionniers des efforts visant à développer des API et des fonctionnalités standardisées pour le Web en tant qu’environnement de développement. Les API telles que fetch(), ReadableStream et WritableStream, URL, URLPattern, TextEncoder, etc. sont devenues des composants omniprésents et précieux du développement Web moderne. Cependant, les chartes de ces groupes existants ont toujours été explicitement limitées à ne prendre en compte que les besoins spécifiques des navigateurs Web, ce qui a entraîné l’élaboration de normes qui ne sont pas facilement optimisées pour tout environnement qui ne ressemble pas exactement à un navigateur Web. Un bon exemple de cet effet est que certaines implémentations non navigateur de la norme Streams sont un ordre de grandeur plus lent que les implémentations équivalentes de Node.js streams et de lecteur Deno en grande partie en raison de la façon dont l’API est spécifiée dans la norme.

Les environnements sans serveur tels que Cloudflare Workers, ou les moteurs d'exécution tels que Node.js et Deno, ont un large éventail d'exigences, de problèmes et de préoccupations qui ne sont tout simplement pas pertinents pour les navigateurs web, et vice versa. Cette déconnexion et l'absence de prise en compte claire de ces différences lors de l'élaboration des diverses spécifications ont conduit à une situation où les moteurs d'exécution sans navigateur ont mis en œuvre leurs propres solutions sur mesure et ad hoc pour des fonctionnalités qui sont en fait communes à tous les environnements.

Ce nouvel effort change la donne en offrant un lieu de discussion et de défense des exigences communes de tous les environnements web, déployés partout dans la pile.

Quels sont les avantages pour les développeurs ?

Les développeurs veulent que leur code soit portable. Une fois qu'ils l'ont écrit, s'ils choisissent de passer à un autre environnement (de Node.js à Deno, par exemple), ils ne veulent pas avoir à le réécrire complètement juste pour qu'il continue à faire exactement la même chose qu'avant.

L'une des questions les plus courantes que nous posent les utilisateurs de Cloudflare est de savoir comment ils peuvent utiliser un module arbitraire publié sur npm qui fait appel à un ensemble d'API spécifiques à Node.js ou à Deno. La réponse implique généralement l'utilisation d'une combinaison arbitraire d'implémentations polyfill. La situation est similaire avec le projet Deno, qui a choisi d'intégrer un polyfill de l'API principale de Node.js directement dans sa bibliothèque standard. Plus ces environnements mettent en œuvre les mêmes normes communes, plus l'écosystème des développeurs peut compter sur le fait que le code qu'ils écrivent fonctionne, quel que soit l'endroit où il est exécuté.

Cloudflare Workers, Node.js, Deno et les navigateurs Web sont tous très différents les uns des autres, mais ils partagent un bon nombre de fonctions communes. Par exemple, ils fournissent tous des API pour générer des hachages cryptographiques, ils traitent tous d'une manière ou d'une autre des données en continu et ils offrent tous la possibilité d'envoyer une requête HTTP quelque part. Lorsque ce chevauchement existe, et lorsque les exigences et les fonctionnalités sont les mêmes, les environnements devraient tous mettre en œuvre les mêmes mécanismes normalisés.

Groupe communautaire sur les moteurs d'exécution interopérables sur le Web

Le nouveau groupe communautaire Web-interoperable Runtimes (ou « WinterCG ») fonctionne selon les processus établis du W3C.

Nous avons mis du temps à nous mettre d'accord sur le nom de ce groupe, car il est essentiel pour comprendre les objectifs que le groupe tente d'atteindre (et ce qu'il n'est pas). L'élément clé est l'expression « web-interoperable ».

Nous utilisons  « web»» exactement dans le même sens que les communautés W3C et WHATWG utilisent ce terme - précisément : navigateurs web. Le terme « web-interoperable » signifie donc que les fonctionnalités sont implémentées d'une manière qui est identique ou au moins aussi cohérente que possible avec la manière dont ces fonctionnalités sont implémentées dans les navigateurs web. Par exemple, la manière dont le constructeur  new URL() fonctionne dans les navigateurs est exactement la manière dont le constructeur  new URL() devrait fonctionner dans Node.js, dans Deno et dans Cloudflare Workers.

Il est toutefois important de reconnaître le fait que Node.js, Deno et Cloudflare Workers ne sont pas explicitement des navigateurs Web. Bien que ce point devrait être évident, il est important de le souligner car les différences entre les divers environnements JavaScript peuvent avoir un impact considérable sur les décisions de conception des API normalisées. Node.js et Deno, par exemple, offrent chacun un accès complet au système de fichiers local. Cloudflare Workers, en revanche, n'a pas de système de fichiers local, et les navigateurs Web empêchent nécessairement les applications de manipuler le système de fichiers local. De même, alors que les navigateurs Web intègrent intrinsèquement le concept de l'« origine » d'un site Web et mettent en œuvre des mécanismes tels que CORS pour protéger les utilisateurs contre toute une série de menaces pour la sécurité, il n'existe aucun concept équivalent d'« origines » du côté serveur où fonctionnent Node.js, Deno et Cloudflare Workers.

Jusqu'à présent, le W3C et le WHATWG se sont strictement préoccupés des besoins des navigateurs web. Le nouveau Web-interoperable Runtimes Community Group s'intéresse explicitement aux besoins de tous les autres et les défend.

Il n'est pas prévu que WinterCG publie son propre ensemble d'API standard indépendantes. Les idées de nouvelles spécifications issues de WinterCG seront d'abord soumises à l'examen des groupes de travail existants du W3C et du WHATWG, dans le but d'obtenir le plus large consensus possible. Toutefois, s'il s'avère que les navigateurs Web n'ont pas de besoin particulier ou d'intérêt pour une fonctionnalité dont les autres environnements (tels que Cloudflare Workers) ont besoin, WinterCG sera habilité à aller de l'avant avec une spécification qui lui est propre - avec la contrainte de ne rien introduire qui soit intentionnellement en conflit ou incompatible avec les normes Web établies.

WinterCG sera ouvert à la participation de tous ; il fonctionnera selon les processus et les politiques établis du W3C ; tous les travaux seront librement accessibles via l'organisation GitHub « wintercg » ; et tout ce qu'il fera sera centré sur l'objectif de maximiser l'interopérabilité.

Travaux en cours

WinterCG a déjà commencé à travailler sur un certain nombre de points importants.

L'API Web minimale commune

Extrait de l'introduction de l'actuel projet de spécification https://github.com/wintercg/proposal-common-minimum-api :

« L'API minimale commune de plate-forme Web est un sous-ensemble sélectionné d'API de plate-formes Web normalisées, destiné à définir un ensemble minimal de capacités communes aux environnements d'exécution JavaScript basés sur un navigateur ou non. »

Ou dit autrement : il s'agit d'un ensemble minimal d'API Web existantes qui seront mises en œuvre de manière cohérente et correcte dans Node.js, Deno et Cloudflare Workers. La plupart des API, à quelques exceptions et nuances près, existent déjà dans ces environnements. Le gros du travail restant consiste donc à s'assurer que ces implémentations sont conformes à leurs spécifications respectives et portables d'un environnement à l'autre.

Le tableau ci-dessous répertorie toutes les API actuellement incluses dans ce sous-ensemble (et indique si l'API est actuellement ou probablement bientôt prise en charge par Node.js, Deno et Cloudflare Workers) :

Node.js Deno Cloudflare Workers
AbortController ✔️ ✔️ ✔️
AbortSignal ✔️ ✔️ ✔️
ByteLengthQueueingStrategy ✔️ ✔️ ✔️
CompressionStream ✔️ ✔️ ✔️
CountQueueingStrategy ✔️ ✔️ ✔️
Crypto ✔️ ✔️ ✔️
CryptoKey ✔️ ✔️ ✔️
DecompressionStream ✔️ ✔️ ✔️
DOMException ✔️ ✔️ ✔️
Event ✔️ ✔️ ✔️
EventTarget ✔️ ✔️ ✔️
ReadableByteStreamController ✔️ ✔️ ✔️
ReadableStream ✔️ ✔️ ✔️
ReadableStreamBYOBReader ✔️ ✔️ ✔️
ReadableStreamBYOBRequest ✔️ ✔️ ✔️
ReadableStreamDefaultController ✔️ ✔️ ✔️
ReadableStreamDefaultReader ✔️ ✔️ ✔️
SubtleCrypto ✔️ ✔️ ✔️
TextDecoder ✔️ ✔️ ✔️
TextDecoderStream ✔️ ✔️ (bientôt)
TextEncoder ✔️ ✔️ ✔️
TextEncoderStream ✔️ ✔️
TransformStream ✔️ ✔️ ✔️
TransformStreamDefaultController ✔️ ✔️ (bientôt)
URL ✔️ ✔️ ✔️
URLPattern ? ✔️ ✔️
URLSearchParams ✔️ ✔️ ✔️
WritableStream ✔️ ✔️ ✔️
WritableStreamDefaultController ✔️ ✔️ ✔️
globalThis.self ? ✔️ (bientôt)
globalThis.atob() ✔️ ✔️ ✔️
globalThis.btoa() ✔️ ✔️ ✔️
globalThis.console ✔️ ✔️ ✔️
globalThis.crypto ✔️ ✔️ ✔️
globalThis.navigator.userAgent ? ✔️ ✔️
globalThis.queueMicrotask() ✔️ ✔️ ✔️
globalThis.setTimeout() / globalthis.clearTimeout() ✔️ ✔️ ✔️
globalThis.setInterval() / globalThis.clearInterval() ✔️ ✔️ ✔️
globalThis.structuredClone() ✔️ ✔️ ✔️

Si l'un des environnements s'écarte de la définition normalisée de l'API (comme la mise en œuvre par Node.js de setTimeout() et setInterval() ), une documentation claire décrivant les différences sera mise à disposition. De telles différences ne devraient exister que pour la compatibilité ascendante avec le code existant.

Flux de cryptographie sur le Web

L'API de cryptographie Web fournit une API  minimale (et très limitée) pour les opérations de cryptographie courantes. L'une de ses principales limitations est le fait que - contrairement au module cryptographique intégré de Node.js - il ne prend pas en charge le streaming des entrées et des sorties des algorithmes cryptographiques symétriques. Toutes les fonctions de cryptographie Web fonctionnent sur des blocs de données conservés en mémoire, en une seule fois. Cela limite strictement les performances et l'évolutivité des opérations cryptographiques. L'utilisation de ces API dans un environnement qui n'est pas un navigateur Web, et la tentative de les rendre performantes, deviennent rapidement pénibles.

Pour résoudre ce problème, le WinterCG a commencé à rédiger, à l'adresse, une nouvelle spécification pour les flux cryptographiques Web qui sera soumise au W3C pour examen dans le cadre d'un effort plus important actuellement déployé par le W3C pour mettre à jour la spécification de la cryptographie Web. L'objectif est d'apporter les opérations de crypto streaming à l'ensemble du We, y compris les navigateurs Web, d'une manière conforme aux normes existantes.

Un sous-ensemble de fetch() pour les serveurs

Avec la récente publication de la version 18.0.0, Node.js a rejoint la collection d'environnements JavaScript qui fournissent une implémentation de l'API normalisée WHATWG  fetch(). Il existe toutefois un certain nombre de différences importantes entre la manière dont Node.js, Deno et Cloudflare Workers mettent en œuvre fetch() et la manière dont elle est mise en œuvre dans les navigateurs Web.

Tout d'abord, les environnements de serveur n'ont pas le concept d'« origine » comme le fait un navigateur web. Des fonctionnalités telles que CORS, destinées à protéger contre les vulnérabilités de script de site à site, ne sont tout simplement pas pertinentes sur le serveur. De même, alors que les navigateurs web sont généralement utilisés par un utilisateur individuel à la fois et ont un concept de magasin de cookies à portée globale, les applications serveur et sans serveur peuvent être utilisées par des millions d'utilisateurs simultanément et un magasin de cookies à portée globale qui contient potentiellement des détails de session et d'authentification serait à la fois peu pratique et dangereux.

En raison des différences marquées entre les environnements, il est souvent difficile de raisonner et d'obtenir un consensus sur les changements proposés dans la norme fetch. Une nouvelle API proposée, par exemple, pourrait être fantastiquement pertinente pour les utilisateurs de fetch sur un serveur mais complètement inutile pour les utilisateurs de fetch dans un navigateur web. Un ensemble de problèmes de sécurité pertinents pour le navigateur pourrait n'avoir aucun impact sur le serveur.

Pour résoudre ce problème et faciliter l'implémentation de fetch de manière cohérente dans les environnements autres que les navigateurs Web, le WinterCG travaille à la documentation d'un sous-ensemble de la norme fetch qui traite spécifiquement de ces différentes exigences et contraintes.

Ce sous-ensemble sera entièrement compatible avec la norme fetch et est développé en coopération par les mêmes personnes qui ont travaillé sur fetch dans Node.js, Deno et Cloudflare Workers. Il n'est pas prévu que cela devienne une définition concurrente de la norme fetch, mais plutôt un ensemble de directives documentées sur la façon d'implémenter correctement fetch dans ces autres environnements.

Nous ne faisons que commencer

Le groupe communautaire « Runtimes interopérables sur le Web » vient juste de démarrer et nous avons un certain nombre d'objectifs ambitieux. La participation est ouverte à tous, et tous les travaux seront réalisés en toute transparence via GitHub à l'adresse https://github.com/wintercg. Nous cherchons activement à collaborer avec le W3C, le WHATWG et la communauté JavaScript dans son ensemble pour faire en sorte que les fonctionnalités Web soient disponibles, fonctionnent de manière cohérente et répondent aux exigences de tous les développeurs Web travaillant n'importe où dans la pile.

Pour plus d'informations sur le WinterCG, consultez le site https://wintercg.org. Pour plus de détails sur la façon de participer, consultez https://github.com/wintercg/admin.