Aller au contenu principal

Version 7.9.0 : Sortie réduite pour preset-env, support de TypeScript 3.8 et nouvelle transformation JSX

· 10 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 →

Alors que nous préparons la version 8.0.0 (dans les prochains mois), nous venons de finaliser une nouvelle version mineure incluant des mises à jour concernant @babel/preset-env, TypeScript 3.8, Flow et JSX !

Il y a quelques mois, Jason Miller a commencé à travailler sur @babel/preset-modules : une expérience visant à réduire considérablement la taille des bundles grâce au modèle module/nomodule. Nous sommes ravis d'annoncer que ces fonctionnalités ont été intégrées à @babel/preset-env ! Ainsi, ces optimisations s'appliquent désormais à toutes les valeurs cibles de preset-env, sans nécessiter de preset supplémentaire.

Note : Ces optimisations seront activées par défaut dans Babel 8. Elles peuvent être activées manuellement dans Babel 7.9 en passant l'option { bugfixes: true } à preset-env.

Cette version prend également pleinement en charge TypeScript 3.8 avec ses imports/exports typés explicites (ex. export type { foo }), ainsi que Flow 0.120 et son modificateur declare pour les champs de classe (ex. class C { declare foo: string }).

Nous avons également collaboré avec l'équipe React pour proposer une nouvelle transformation JSX, permettant à React et aux bibliothèques similaires d'optimiser la création d'éléments JSX via la fonction jsx plutôt que React.createElement.

Enfin, @babel/parser prend désormais en charge une nouvelle proposition ECMAScript : Record & Tuple. Notez qu'il s'agit uniquement d'un support dans l'analyseur syntaxique, les transformations étant encore en développement.

Vous pouvez consulter l'intégralité du journal des modifications sur GitHub.


Un grand merci à Luna Ruan de l'équipe React (Facebook) pour sa contribution à la nouvelle transformation JSX, et à Rick Button (Bloomberg) pour l'implémentation du support de la proposition Record & Tuple dans l'analyseur syntaxique !

Si vous ou votre entreprise souhaitez soutenir Babel et l'évolution de JavaScript sans savoir comment procéder, vous pouvez nous faire un don via notre Open Collective ou mieux encore, collaborer directement avec nous à l'implémentation de nouvelles propositions ECMAScript ! Projet reposant sur le bénévolat, nous comptons sur le soutien communautaire pour financer nos efforts au service de la diversité des utilisateurs JavaScript. Contactez-nous à team@babeljs.io pour en discuter !

Option bugfixes de @babel/preset-env (#11083)

La nouvelle option bugfixes de @babel/preset-env remplace directement l'utilisation de @babel/preset-modules.

Pour plus de contexte sur les problèmes résolus par cette modification, nous vous recommandons d'écouter (ou lire) les épisodes récents du podcast avec Jason : #2 Modern JavaScript and the Future of preset-env et #3 Compiling Your Dependencies.

Jusqu'à présent, @babel/preset-env (et les plugins Babel en général) regroupaient les fonctionnalités syntaxiques d'ECMAScript en collections de petites fonctionnalités étroitement liées. Ces groupes pouvaient être volumineux et inclure de nombreux cas particuliers. Par exemple, le groupe « paramètres de fonction » et son plugin incluent les paramètres destructurés, par défaut et rest.

À partir de ces informations de regroupement, Babel active ou désactive chaque groupe selon la cible de support navigateur spécifiée dans l'option targets de @babel/preset-env.

Voici le problème : si une version quelconque d'un navigateur de cette liste contient un bogue déclenché par une syntaxe moderne, la seule solution (que nous envisagions à l'époque) était d'activer le groupe de transformation correspondant qui corrige ce bogue.

Avec le temps, davantage de bogues ont été découverts et signalés dans nos issues, ce qui a conduit preset-env à produire plus de code pour couvrir ces cas particuliers. Dans le pire des cas, cela signifiait que le résultat équivalait à une compilation complète en ES5, ce que preset-env était justement conçu pour éviter.

Lorsque l'option bugfixes: true est activée, @babel/preset-env adopte une approche différente : il transcompile la syntaxe défectueuse vers la syntaxe moderne non défectueuse la plus proche.

Exemple : toutes les nouvelles fonctionnalités syntaxiques liées aux paramètres de fonction sont regroupées dans le même plugin Babel (@babel/plugin-transform-function-parameters). Lors du ciblage de edge 16, un bogue affecte l'analyse des paramètres destructurés en forme abrégée avec valeurs par défaut dans les fonctions fléchées :

JavaScript
// this breaks in Edge 16:
const foo = ({ a = 1 }) => {};

// .. but this doesn't:
function foo({ a = 1, b }, ...args) {}

// ... and neither does this:
const foo = ({ a: a = 1 }) => {};

Cela signifie que si nous fournissons cette entrée à @babel/preset-env en ciblant Edge 16 :

JavaScript
const foo = ({ a = 1 }, b = 2, ...args) => [a, b, args];

Il transforme les paramètres en syntaxe de type ES5 :

JavaScript
const foo = function foo(_ref, b) {
let { a = 1 } = _ref;

if (b === void 0) { b = 2; }

for (
var _len = arguments.length,
args = new Array(_len > 2 ? _len - 2 : 0),
_key = 2; _key < _len; _key++
) {
args[_key - 2] = arguments[_key];
}

return [a, b, args];
};

Cependant, si nous activons l'option bugfixes, seule la syntaxe défectueuse est transformée :

JavaScript
const foo = ({ a: a = 1 }, b = 2, ...args) => [a, b, args];

Vous pouvez tester cet exemple dans notre REPL

Vous pouvez activer cette option dès maintenant en l'ajoutant à @babel/preset-env dans votre configuration :

{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true
}]
]
}
astuce

Actuellement, l'option bugfixes donne les meilleurs résultats avec la cible esmodules: true, qui permet de cibler les navigateurs supportant les modules ES natifs via le motif module/nomodule. Nous prévoyons de continuer à l'améliorer dans les prochaines versions et de l'activer par défaut dans Babel 8.

À l'avenir, nous souhaitons collaborer avec la communauté (y compris les navigateurs) pour que cette approche fonctionne harmonieusement dans l'évolution continue de JavaScript. Dans le scénario idéal, Babel pourrait implémenter et contribuer à influencer l'avenir des nouvelles propositions au fur et à mesure de leur conception, tout en lissant ces cas particuliers pour les standards existants. Ainsi, la compilation minimale serait garantie pour tous les utilisateurs de JavaScript en fonction de leurs cibles.

TypeScript 3.8 : imports/exports typés uniquement (#11171)

Vous pouvez désormais marquer explicitement les imports et exports comme étant uniquement des types, de la même manière que ce que vous permet déjà Flow :

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

Ainsi, Babel peut déterminer de manière sûre quels imports ou exports sont utilisés pour des types et lesquels représentent des valeurs.

Comme Babel n'analyse pas les types et fonctionne fichier par fichier (similairement à l'option --isolatedModules de TypeScript), jusqu'à présent @babel/plugin-transform-typescript traitait les imports non utilisés comme valeurs comme s'ils étaient exclusivement des types.

À partir de Babel 7.9, vous pouvez utiliser le nouveau modificateur type sans aucune modification de configuration.

Nous recommandons de configurer @babel/preset-typescript ou @babel/plugin-transform-typescript pour qu'ils ne considèrent les imports comme uniquement typés qu'en présence du mot-clé explicite type, similairement à l'option --importsNotUsedAsValues preserve de TypeScript :

babel.config.json
{
"presets": [
["@babel/preset-typescript", {
"onlyRemoveTypeImports": true
}]
]
}
astuce

Ces fonctionnalités ont été développées conjointement par l'équipe Babel et Siddhant N Trivedi. Si vous souhaitez comprendre leur implémentation, découvrez notre démarche sur YouTube !

Champs declare pour Flow (#11178)

La proposition des champs de classe spécifie que les champs non initialisés sont définis sur undefined : ce comportement diffère de celui de Babel avec Flow, qui les ignore simplement.

Pour cette raison, l'équipe Flow a ajouté la prise en charge du modificateur declare pour les champs de classe :

JavaScript
class Foo {
x: ?string; // A "real" field
declare y: number; // A type-only field
}

Dans l'exemple ci-dessus, seul y devrait être entièrement supprimé par Babel.

Pour éviter les breaking changes, nous avons introduit la prise en charge de declare dans les champs de classe via un flag : "allowDeclareFields", supporté à la fois par @babel/plugin-transform-flow et @babel/preset-flow. Cela deviendra le comportement par défaut dans Babel 8, nous vous recommandons donc de migrer votre configuration pour l'utiliser :

babel.config.json
{
"presets": [
["@babel/preset-flow", {
"allowDeclareFields": true
}]
]
}

Une nouvelle transformation JSX (#11154)

L'équipe React a créé une RFC en février dernier pour simplifier la création d'éléments.

Dans une future version stable, React prendra en charge de nouvelles fonctions dédiées à l'instanciation des éléments JSX, remplaçant l'approche générique actuelle avec React.createElement. Cela permettra de futures optimisations.

astuce

Bien que non disponible en version stable, vous pouvez l'essayer via le canal expérimental de React :

Shell
npm install react@experimental react-dom@experimental

Nous avons collaboré avec l'équipe pour finaliser une nouvelle transformation compilant JSX vers ces nouvelles fonctions. Elle importe automatiquement "react" (ou d'autres bibliothèques compatibles) quand nécessaire, éliminant l'obligation de l'inclure manuellement.

Par exemple, ce code source :

JSX
function Foo() {
return <div />;
}

deviendrait :

JSX
import { jsx as _jsx } from "react/jsx-runtime";
function Foo() {
return _jsx("div", ...);
}

Note : Les fonctions dans react/jsx-runtime et react/jsx-dev-runtime ne sont pas destinées à une utilisation externe aux plugins @babel/plugin-transform-react-jsx et @babel/plugin-transform-react-jsx-development.

En résumé (consultez la RFC pour plus de détails), la transformation :

  • Passe systématiquement les enfants via les props.

  • Traite key séparément des autres props.

  • En mode DEV,

    • Transmettre un indicateur déterminant si l'élément était statique ou non.
    • Transmettre __source et __self séparément des autres props.

Utilisation : Activez cette nouvelle transformation en passant { "runtime": "automatic" } (au lieu de "classic") à @babel/preset-react ou @babel/plugin-transform-react-jsx :

babel.config.json
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}

À partir de Babel 8, "automatic" deviendra le runtime par défaut.

Vous pouvez également activer le mode développement pour cette transformation via @babel/plugin-transform-react-jsx-development ou en passant { "development": true, "runtime": "automatic" } à @babel/preset-react.

Consultez la documentation pour plus de détails sur cette nouvelle transformation.