Aller au contenu principal

Approche de la version 7.0

· 17 min de lecture
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 →

Consultez Planning for 7.0 pour les dernières mises à jour des pré-releases 7.0. Si quelque chose n'est pas clair dans ce billet, faites-le moi savoir !

Mises à jour du projet

  • Nous avons lancé une nouvelle page de vidéos ! Nous l'avons créée pour ceux qui souhaitent approfondir le fonctionnement de Babel et aider d'autres contributeurs. Cette page contient des conférences vidéo sur Babel et des concepts connexes par des membres de l'équipe et la communauté (vous pouvez soumettre une PR si vous avez fait une présentation similaire).

vidéos

  • Nous avons également créé une nouvelle page de l'équipe ! Nous mettrons à jour cette page ultérieurement avec plus d'informations sur les rôles et motivations des membres. Pour un projet de cette ampleur, il existe de nombreuses façons de s'impliquer et d'aider.

équipe

  • Babel a fêté ses 3 ans le 28 septembre 2017 !

  • Daniel a déplacé babel/babylon et babel/babel-preset-env dans le monorepo principal babel/babel, en conservant l'historique git, les labels et issues.

  • Nous avons reçu un don de 1 000 $/mois de Facebook Open Source !

    • Il s'agit du don mensuel le plus important depuis nos débuts (le suivant est de 100 $/mois).
    • En attendant, nous utiliserons ces fonds pour organiser des rencontres en personne et envoyer des membres aux réunions TC39. Ces réunions ont lieu tous les 2 mois à travers le monde.
    • Si une entreprise souhaite sponsoriser une action spécifique, nous pouvons créer des issues dédiées. Cela était difficile auparavant car nous devions payer de notre poche ou trouver des conférences la même semaine pour couvrir les frais.

Comment pouvez-vous aider ?

Si votre entreprise souhaite redonner à la communauté en soutenant une brique fondamentale du développement JavaScript et son avenir, envisagez de faire un don sur notre Open Collective. Vous pouvez également contribuer en temps de développeur pour maintenir le projet.

#1 Aidez à maintenir le projet (temps de développeur au travail)

La meilleure contribution pour ce projet est l'engagement de personnes prêtes à aider compte tenu du travail et des responsabilités considérables. Comme je l'ai déjà dit, je ne me suis jamais senti prêt à devenir mainteneur mais j'ai atterri là par hasard. Je ne suis qu'une seule personne, et notre équipe est très réduite.

#2 Financez le développement

Nous cherchons activement à financer des membres de l'équipe pour un travail à plein temps. Logan a notamment quitté son emploi et utilise nos fonds actuels pour travailler sur Babel à temps partiel !

#3 Contribuez autrement 😊

Par exemple, Angus nous a composé une chanson officielle !

Mise à niveau

Nous travaillons également sur un outil de mise à niveau qui aidera à réécrire vos fichiers package.json/.babelrc et plus encore. Idéalement, il modifiera automatiquement les numéros de version nécessaires, les renommages de packages et les changements de configuration.

N'hésitez pas à nous solliciter pour obtenir de l'aide et à signaler les problèmes rencontrés lors de la mise à jour ! C'est une excellente opportunité pour contribuer et aider l'écosystème à se mettre à jour !

Récapitulatif du billet précédent

  • Abandon de la prise en charge de Node 0.10/0.12/5.

  • Mise à jour des propositions TC39

    • Séparateur numérique : 1_000
    • Opérateur de chaînage optionnel : a?.b
    • import.meta (analysable)
    • Liaison de catch optionnelle : try { a } catch {}
    • BigInt (analysable) : 2n
    • Séparation des extensions d'export en export-default-from et export-ns-form
  • Prise en charge de .babelrc.js (configuration JavaScript au lieu de JSON)

  • Ajout d'un nouveau preset TypeScript + séparation des presets React/Flow

  • Suppression de la dépendance interne babel-runtime pour réduire la taille

Propositions TC39 récemment mises à jour

  • Opérateur pipeline : a |> b

  • Expressions throw : () => throw 'hi'

  • Opérateur de coalescence des nuls : a ?? b

Dépréciation des presets annuels (ex: babel-preset-es20xx)

TL;DR : utilisez babel-preset-env.

Quoi de mieux que de devoir choisir quel preset Babel utiliser ? L'automatisation de cette décision !

Bien que le travail de maintenance des jeux de données soit colossal — d'où notre besoin d'aide — cette solution résout plusieurs problèmes. Elle garantit que les utilisateurs restent à jour avec la spécification, simplifie la configuration, facilite les mises à niveau et réduit les questions sur les différences entre presets.

babel-preset-env est en réalité un preset plutôt ancien qui remplace tous les autres presets de syntaxe dont vous pourriez avoir besoin (es2015, es2016, es2017, es20xx, latest, etc...).

npm presets

Il compile la dernière version annuelle de JavaScript (tout ce qui est en Stage 4), remplaçant ainsi les anciens presets. Mais il permet aussi de compiler selon des environnements cibles spécifiés : que ce soit pour du développement (dernières versions de navigateurs) ou pour des builds multiples (une version pour IE, une autre pour les navigateurs modernes).

Conservation des presets de stage (babel-preset-stage-x)

MÀJ : Nous les avons finalement supprimés, expliqué ici

Nous pouvons toujours les maintenir à jour, mais nous devons probablement concevoir un meilleur système que celui actuellement utilisé pour ces presets.

Actuellement, les presets de stage sont simplement une liste de plugins que nous mettons à jour manuellement après les réunions du TC39. Pour rendre cela gérable, nous devons autoriser des mises à jour majeures de version pour ces packages "instables". Une partie de la raison est que la communauté recréera de toute façon ces packages, donc autant le faire via un package officiel pour pouvoir fournir de meilleurs messages, etc.

Renommage : Packages Scoped (@babel/x)

Voici un sondage que j'ai réalisé il y a presque un an :

À l'époque, peu de projets utilisaient des packages scoped, donc la plupart des gens ignoraient même leur existence. Il fallait aussi payer pour un compte npm org, alors que maintenant c'est gratuit (et cela prend aussi en charge les packages non scoped). Les problèmes de recherche des packages scoped sont résolus et les compteurs de téléchargements fonctionnent. Le seul point restant est que certains registres tiers ne prennent toujours pas en charge les packages scoped, et je pense qu'il est désormais déraisonnable d'attendre cela.

Si vous voulez savoir pourquoi nous préférons les packages scoped :

  • Le nommage est difficile : nous n'aurons plus à vérifier si quelqu'un utilise notre convention de nommage pour son propre plugin

  • De même, le package squatting

    • Parfois des personnes créent babel-preset-20xx par amusement, et nous devons ouvrir un ticket/demander par email pour récupérer le nom.
    • Des packages légitimes portent accidentellement le même nom que ceux que nous voulons utiliser.
    • Des personnes voient qu'une nouvelle proposition est en cours (comme le chaînage optionnel ou l'opérateur pipeline), forkent et publient une version sous le même nom. Quand nous publions, on nous dit que le package existe déjà 🤔. Je dois alors contacter l'auteur et le support npm pour récupérer le package et republier.
  • Comment distinguer un package officiel d'un package communautaire homonyme ? Nous recevons des rapports de bugs de personnes utilisant des packages non officiels car elles pensaient qu'ils faisaient partie de Babel. Par exemple, un rapport indiquait que babel-env réécrivait leur fichier .babelrc, et il a fallu du temps pour réaliser que ce n'était pas babel-preset-env.

Il semble donc évident que nous devrions utiliser des packages scoped, et nous aurions même dû le faire plus tôt 🙂 !

Exemples de changement de nom en version scoped :

  • babel-cli -> @babel/cli

  • babel-core -> @babel/core

  • babel-preset-env -> @babel/preset-env

Renommage : -proposal-

Toutes les propositions seront désormais préfixées par -proposal- pour indiquer qu'elles ne font pas encore officiellement partie de JavaScript.

Ainsi @babel/plugin-transform-class-properties devient @babel/plugin-proposal-class-properties, et nous le renommerons une fois le Stage 4 atteint.

Renommage : Suppression de l'année dans le nom des plugins

Les plugins précédents incluaient l'année dans leur nom, mais cela n'est plus nécessaire désormais.

Donc @babel/plugin-transform-es2015-classes devient @babel/plugin-transform-classes.

Comme les années ne concernaient que es3/es2015, nous n'avons rien changé pour es2016 ou es2017. Cependant, nous déprécions ces presets au profit de preset-env. Pour la révision des littéraux de gabarit, nous l'avons simplement intégrée au transform existant par simplicité.

Dépendances Peer + Intégrations

Nous introduisons une dépendance peer sur @babel/core pour tous les plugins (@babel/plugin-class-properties), presets (@babel/preset-env) et packages de premier niveau (@babel/cli, babel-loader).

Les peerDependencies sont des dépendances que votre code est censé utiliser, par opposition aux dépendances utilisées uniquement comme détail d'implémentation. — Stijn de Witt via StackOverflow

babel-loader avait déjà une peerDependency sur babel-core, cette modification la remplace simplement par @babel/core. Cela évite que les utilisateurs n'installent ces paquets avec une version incorrecte de Babel.

Pour les outils ayant déjà une peerDependency sur babel-core et qui ne sont pas prêts pour une mise à jour majeure (car modifier une peerDependency est un changement cassant), nous avons publié une nouvelle version de babel-core pour assurer la transition : babel-core@7.0.0-bridge.0. Pour plus d'informations, consultez cette issue.

De même, des paquets comme gulp-babel, rollup-plugin-babel, etc., avaient babel-core comme dépendance. Ils auront désormais une peerDependency sur @babel/core. Cela permet à ces paquets d'éviter une mise à jour majeure lorsque l'API de @babel/core n'a pas changé.

#5224 Publication indépendante des paquets expérimentaux

J'évoquais cela dans The State of Babel dans la section Versioning. Issue Github

Vous vous souvenez peut-être qu'après Babel 6, Babel est devenu un ensemble de paquets npm avec son propre écosystème de presets et plugins personnalisés.

Cependant depuis, nous avons toujours utilisé un versionnage "fixe/synchronisé" (aucun paquet n'est en v7.0 ou supérieur). Lors d'une nouvelle version comme v6.23.0, seuls les paquets dont le code source a été modifié sont publiés avec la nouvelle version, les autres restant inchangés. Cela fonctionne généralement grâce à l'utilisation de ^ dans nos paquets.

Malheureusement, ce système impose qu'une version majeure soit publiée pour tous les paquets dès qu'un seul en a besoin. Cela signifie soit faire beaucoup de petits changements cassants (inutiles), soit regrouper de nombreuses modifications majeures dans une seule version. Nous préférons différencier les paquets expérimentaux (Stage 0, etc.) du reste (es2015).

Nous prévoyons donc de faire des mises à jour majeures pour les plugins de propositions expérimentales lorsque la spécification change, sans attendre de mettre à jour tout Babel. Tout ce qui est < Stage 4 pourra subir des changements cassants via des versions majeures, idem pour les presets de stage (si nous ne les abandonnons pas totalement).

Cela s'aligne avec notre décision de renommer les plugins pour propositions TC39 avec le suffixe -proposal-. Si la spécification change, nous ferons une version majeure du plugin et du preset correspondant (plutôt qu'une version patch qui pourrait casser des projets). Nous devrons alors déprécier les anciennes versions et mettre en place une infrastructure de mise à jour automatique pour maintenir les utilisateurs à jour avec l'évolution de la spécification (et éviter qu'ils ne restent bloqués, comme avec les décorateurs).

L'option env dans .babelrc n'est PAS dépréciée !

Contrairement à ce qui était annoncé dans le précédent billet, nous avons simplement corrigé le comportement de fusion pour le rendre plus cohérent.

La configuration dans env a désormais priorité sur les éléments racines, et au lieu d'une approche ambiguë combinant les deux, les plugins et presets fusionnent maintenant selon leur identité, ce qui permet de faire :

JavaScript
{
presets: [
['env', { modules: false}],
],
env: {
test: {
presets: [
'env'
],
}
},
}

avec BABEL_ENV=test, ce qui remplace la configuration env racine par celle du test, qui n'a pas d'options.

Prise en charge de class A extends Array (caveat historique)

Babel encapsulera automatiquement les built-ins natifs comme Array, Error, HTMLElement etc. pour que cette syntaxe fonctionne lors de la compilation des classes.

Performances

preset-env: "useBuiltins": "usage"

babel-preset-env a introduit la compilation syntaxique pour différentes cibles, et via l'option useBuiltIns, la capacité à ajouter uniquement les polyfills non supportés par les environnements cibles.

Avec cette option, un code comme :

JavaScript
import "babel-polyfill";

Peut transformer en

JavaScript
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
// ...

si l'environnement cible prend en charge des polyfills autres que padStart ou padEnd.

Cependant, pour que cela soit encore mieux, nous devrions importer uniquement les polyfills "utilisés" dans le codebase lui-même. Pourquoi importer padStart s'il n'est même pas utilisé dans le code ?

"useBuiltins": "usage" est notre première implémentation de cette approche. Il ajoute un import en haut de chaque fichier uniquement si le polyfill est utilisé dans le code. Cela permet d'importer le minimum nécessaire (et seulement si l'environnement cible ne le supporte pas).

Si vous utilisez Promise, il sera importé en haut du fichier (si votre cible ne le supporte pas). Les bundlers dédupliqueront le fichier, évitant ainsi les imports multiples.

JavaScript
import "core-js/modules/es6.promise";
var a = new Promise();
JavaScript
import "core-js/modules/es7.array.includes";
[].includes
a.includes

Grâce à l'inférence de types, nous pouvons détecter si une méthode comme .includes s'applique à un tableau. Les faux positifs sont acceptables en attendant des améliorations, car cette approche reste meilleure qu'importer l'ensemble des polyfills.

Autres mises à jour

  • babel-template est plus rapide et intuitif

  • regenerator est publié sous licence MIT - utilisé pour compiler les générateurs/async

  • Option "lazy" pour le plugin modules-commonjs via #6952

  • Utilisation de envName: "something" dans .babelrc ou en CLI via babel --envName=something (remplace process.env.BABEL_ENV ou process.env.NODE_ENV)

  • ["transform-for-of", { "assumeArray": true }] pour compiler toutes les boucles for-of en tableaux standards

  • Exclusion de transform-typeof-symbol en mode loose pour preset-env #6831

  • Amélioration des messages d'erreur pour les syntaxes invalides

Tâches avant la release

  • Gestion de la recherche de .babelrc (prérequis pour la première RC)

  • Support des "overrides" : configuration différente par motif glob

  • Logique de cache et d'invalidation dans babel-core.

  • Implémenter ou avoir un plan pour gérer indépendamment le versionnage des polyfills et des helpers, afin de ne pas être explicitement lié à core-js 2 ou 3. Les utilisateurs peuvent avoir des dépendances spécifiques à l'une ou l'autre version et souhaitent généralement éviter de charger les deux simultanément.

  • Soit une implémentation fonctionnelle des décorateurs, soit une implémentation héritée opérationnelle, avec une feuille de route claire pour intégrer le comportement actuel de la spécification durant le cycle de vie de la version 7.x.

Remerciements

Un grand merci à notre équipe de bénévoles : Logan qui a travaillé intensément pour corriger des problèmes fondamentaux liés aux configurations, Brian qui a repris la maintenance de preset-env et d'autres travaux 😛, et Daniel toujours présent pour aider, que ce soit sur babel-loader ou la migration des dépôts babylon/babel-preset-env. Merci également à Nicolo, Sven, Artem et Jessica pour leur engagement cette année.

J'attends cette version avec impatience (cela fait presque un an, la fatigue se fait sentir 😝), mais sans précipitation inutile. Ce cycle de publication a connu des hauts et des bas, mais j'ai énormément appris, comme le reste de l'équipe.

Et s'il y a une leçon à retenir cette année, c'est bien de mettre en pratique ces conseils plutôt que de simplement les écrire.

Merci aussi à Mariko pour la petite poussée qui m'a permis de terminer cet article (2 mois de travail)