Aller au contenu principal

Feuille de route de Babel

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

Ce document présente certaines améliorations que les membres de notre équipe souhaitent réaliser cette année.

Cette liste est loin d'être exhaustive concernant les nouvelles fonctionnalités ou changements majeurs que nous apporterons à Babel, mais elle offre un bon aperçu de l'orientation générale du projet. Nous ne terminerons peut-être pas tous les points listés ou certains pourraient être reportés à l'année prochaine. Certains ont des points de départ et d'arrivée clairs, tandis que d'autres nécessitent davantage de recherche ou de RFCs.

Si votre entreprise souhaite sponsoriser un élément spécifique, contactez-nous !

Feuille de route 2021 de Babel

Babel 8

Nous discutons de la version Babel 8 depuis plus d'un an (initialement prévue il y a environ un an) ! Cependant, nous n'avons jamais été aussi proches de sa sortie !

La plupart des tâches restantes sont dans le ticket de suivi, mais quelques obstacles subsistent :

  • Nous voulons abandonner le support de Node.js 10, dont la maintenance s'arrête le 2021-04-30.

  • Nous souhaitons publier Babel en tant que package ESM pur. Nous convertissons actuellement nos sources pour les rendre compatibles avec l'implémentation ESM de Node.js. Ce faisant, nous étudions comment faciliter l'utilisation de Babel pour compiler ESM vers CJS.

  • Nous travaillons à aligner notre AST TypeScript avec le projet typescript-eslint. Nos AST sont quasiment identiques, mais des changements cassants mineurs sont nécessaires pour un alignement complet.

  • Notre infrastructure de release ne prend pas encore en charge les pré-versions ou l'utilisation de plusieurs branches "main" (une pour Babel 8 et une pour Babel 7).

  • Nous n'avons pas encore défini de politique de maintenance pour Babel 7.

Implémenter les nouvelles propositions TC39

Babel peut actuellement parser toutes les propositions Stage 3 et les transformer à l'exception de top-level await, des assertions d'import et des modules JSON (mieux gérés par les bundlers via le graphe de dépendances).

Nous supportons toutes les propositions Stage 2 sauf :

  • La nouvelle itération des décorateurs (nécessite l'implémentation du parsing et de la transformation) ;

  • La transformation pour les blocs de modules (le parsing est implémenté depuis Babel 7.13.0).

Nous implémenterons le support des décorateurs et étudierons comment transformer les blocs de modules.

Bien que nous ne supportions pas beaucoup de propositions Stage 1, l'opérateur pipeline et les do expressions ont récemment évolué. Comme nous les supportons déjà et que la communauté les attend avec intérêt, nous mettrons à jour nos implémentations.

D'autres propositions (comme le pattern matching) n'ont pas encore été implémentées car leurs responsables prévoient des changements syntaxiques et sémantiques majeurs. Cependant, nous suivons leur développement de près et les implémenterons dans Babel dès qu'elles se stabiliseront.

Intégrer @babel/preset-env dans @babel/core

Une configuration minimale de transformation Babel nécessite au moins trois packages :

  • @babel/core

  • @babel/preset-env

  • un "runner" Babel (@babel/cli, babel-loader, @rollup/plugin-babel, etc.)

L'intégration de @babel/preset-env directement dans @babel/core présente deux avantages majeurs :

  • Cela simplifiera la configuration de Babel dans les projets simples : il suffira d'activer une option compileJS: true dans babel.config.json (ou cela pourrait même devenir la valeur par défaut à l'avenir — impossible actuellement car @babel/eslint-parser ne compile pas le code source)

  • Cela garantira que les versions des plugins restent synchronisées avec la version de @babel/core, évitant ainsi la plupart des bogues causés par des versions de paquets incompatibles

  • Lors du passage à ESM, la résolution et le chargement synchrone des plugins dans transformSync deviendraient complexes. Cette intégration prévient ce problème

Une RFC existe déjà pour intégrer les plugins des fonctionnalités ECMAScript stables dans @babel/core, représentant la première étape de cette démarche

Avec l'architecture actuelle de @babel/preset-env, nous devrions traiter spécifiquement les plugins officiels pour les activer/désactiver automatiquement selon les targets Cependant, cette approche présente deux inconvénients majeurs :

  • Les données de compatibilité d'un plugin sont totalement découplées de son implémentation (ce n'est même pas une dépendance directe, plutôt une dépendance peer implicite interne : plugin -> @babel/core -> @babel/compat-data)

  • Les plugins officiels bénéficieraient d'un traitement privilégié dans @babel/core, alors que nous voulons garantir aux plugins tiers les mêmes capacités qu'aux plugins officiels

Poursuivre le développement du projet babel-polyfills

Nous avons décidé de retirer la prise en charge de core-js@2 de @babel/preset-env dans Babel 8. Nous souhaitons également cesser de promouvoir un polyfill tiers spécifique, ce qui pourrait laisser croire aux utilisateurs qu'il fait partie intégrante de Babel

Cette transition pourra s'opérer de deux manières :

  • Supprimer purement core-js@3 de @babel/preset-env dans Babel 8, en incitant les utilisateurs à migrer vers babel-plugin-polyfill-corejs3 (solution utilisée en interne par @babel/preset-env depuis la version 7.10.0)

  • Maintenir la prise en charge de core-js@3 dans @babel/preset-env, mais ne pas l'intégrer à @babel/core lors du déplacement des plugins de transformation

Quelle que soit l'option retenue, nous proposerons au moins une alternative aux utilisateurs lors de la mise à jour de l'intégration core-js dans leur configuration. core-js reste un excellent polyfill garantissant une conformité maximale aux spécifications, mais certains utilisateurs pourraient préférer d'autres compromis

(Nicolò) collabore avec @ljharb pour s'assurer que le projet @es-shims prenne en charge au moins toutes les fonctionnalités ES2015+ (nous visons en réalité ES5+), offrant ainsi aux utilisateurs de Babel le choix entre au moins deux options

Cette étape doit impérativement précéder l'abandon de la prise en charge intégrée de core-js@3, évitant ainsi une double migration aux utilisateurs intéressés par es-shims

Étendre l'utilisation de targets pour des transformations granulaires

Depuis ses débuts, @babel/preset-env utilise l'option targets pour activer/désactiver automatiquement les plugins de transformation

Cependant, aucune correspondance un-à-un n'existe entre les plugins Babel et les fonctionnalités implémentées dans les navigateurs

Par exemple, un seul plugin gère les différents types de champs de classe (publics/privés, statiques/d'instance), alors que les navigateurs présentent des matrices de compatibilité variables :

  • Firefox 73 et Safari 14 ne prennent en charge que les champs d'instance publics

  • Firefox 75+ prend en charge les champs publics d'instance et statiques

  • Chrome 79+ gère les champs publics et privés, mais pas les champs privés dans certaines expressions de chaînage optionnel

  • Chrome 84+ prend pleinement en charge les champs privés ainsi que les méthodes privées

  • Safari TP 121 prend entièrement en charge les champs privés (même avec ?.), mais ne prend pas en charge les méthodes privées

Créer un plugin pour chaque fonctionnalité est sous-optimal. Par exemple, nous pouvons convertir les méthodes privées en champs privés puis, si nécessaire, les convertir vers une syntaxe plus ancienne. Cependant, nous pouvons générer un résultat meilleur/optimisé en convertissant directement les méthodes privées vers une syntaxe plus ancienne sans étape intermédiaire si nous savons qu'elles doivent être transpilées.

Depuis Babel 7.13.0, nous pouvons lire l'option targets directement dans un plugin. Nous pouvons modifier nos plugins pour effectuer automatiquement une compilation partielle d'une fonctionnalité ECMAScript donnée, ce qui apporterait des avantages en taille de sortie et en performances d'exécution.

Antécédents

Cette approche n'est pas complètement nouvelle. Grâce à une collaboration avec @_developit, nous avons introduit dans Babel 7.9.0 une nouvelle option bugfixes: true pour @babel/preset-env. Lorsque cette option est activée et que esmodules: true est utilisé comme cible de compilation, nous ne compilons que partiellement certaines fonctionnalités. C'est ce qui nous a initialement fait envisager cette possibilité, mais les transformations partielles actuelles sont moins utiles avec des cibles plus modernes (par exemple defaults, not ie 11).

Nous utilisons déjà l'option targets pour décider si nous pouvons employer Object.assign lors de la compilation des spreads d'objets.

Points d'action

Cet objectif peut être divisé en deux grandes tâches réalisables en parallèle :

  • Nous devons identifier ces optimisations peuvent être utiles en collectant des requêtes browserslist réelles et en simulant l'évolution des requêtes populaires (par exemple defaults ou >2%, not dead).

  • Nous devons implémenter concrètement les optimisations nécessaires, en veillant à ce qu'elles fonctionnent toujours bien avec les autres plugins (car elles augmenteraient considérablement le nombre de combinaisons de transformations possibles).

Étudier de nouvelles assumptions du compilateur

Dans Babel 7.13.0, nous avons introduit une nouvelle option globale assumptions pour formaliser le comportement du mode loose et offrir un contrôle plus granulaire à nos utilisateurs (qui peuvent souvent activer seulement certaines assumptions).

Cependant, nous n'avons inclus que des options pour les assumptions que nous faisions déjà en mode loose. Nous pouvons maintenant étudier quelles nouvelles assumptions nos utilisateurs pourraient nécessiter.

Il existe déjà quelques propositions, comme :

  • #8222 - supposer que toutes les importations ESM sont immuables, évitant le code nécessaire pour les liaisons dynamiques.

  • #11356 - supposer que les classes compilées n'étendent pas de classes natives, évitant le coût de performance à l'exécution pour instancier des classes potentiellement natives.

Nous pouvons déterminer quelles nouvelles assumptions implémenter en :

  • Vérifiant manuellement quelles fonctionnalités nous compilons vers un résultat "non évident", généralement causé par des cas limites que la plupart des développeurs ignorent.

  • Demandant des retours à la communauté, car les développeurs peuvent tester quelles assumptions fonctionnent ou non dans leurs applications.

Refondre le REPL de Babel

Le REPL de Babel est un terrain de jeu pratique pour apprendre comment Babel transpile du code source.

Limites actuelles :

Fonctionnalités souhaitables :

  • AST Explorer (intégration avec l'existant)

  • stderr avec trace de pile complète comme journal d'erreurs

  • stdout en sortie

  • Changer la version de Babel depuis l'interface

Au moins 15 % des issues ouvertes sur babel-website concernent le REPL : https://github.com/babel/website/issues?q=is%3Aissue+is%3Aopen+label%3Arepl

Outils pédagogiques et de débogage

En lien avec le REPL/ASTExplorer, nous pourrions développer davantage d'outils pour faciliter le développement de plugins, tant pour nous que pour les plugins tiers. Ce domaine est plutôt exploratoire : différentes visualisations de l'AST lui-même, outils de débogage, etc.

Quelques éléments sur lesquels Henry travaille par intermittence :

  • Codesandbox pour créer un plugin Babel simple dans le même esprit que https://astexplorer.net mais avec des configurations personnalisées.

  • Visualisation du mapping entrée/sortie pour comprendre comment Babel transforme le code. Utile même pour la documentation afin de familiariser les développeurs JavaScript avec de nouvelles syntaxes ou démos spécifiques de transformations.

  • Mapping entrée/sortie de type structure sourcemap. Permet un mapping inverse pour identifier quel plugin a produit un code spécifique, aidant au débogage.

Pour un exemple interactif de notre vision : https://babel-explorer.netlify.app/ (cliquez et maintenez dans le secteur inférieur !)