Aller au contenu principal

Mise à niveau vers Babel 7

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 ce document pour la migration vers Babel 7. Voir ici pour les changements d'API/d'intégration.

Comme chaque changement cassant n'affecte pas tous les projets, nous avons classé les sections par probabilité d'impact sur les tests lors de la mise à niveau.

Tout Babel

La prise en charge de Node.js 0.10, 0.12, 4 et 5 a été abandonnée #5025, #5041, #7755, #5186

Nous vous recommandons vivement d'utiliser une version plus récente de Node.js (LTS v8) car les versions antérieures ne sont plus maintenues. Consultez nodejs/LTS pour plus d'informations.

Cela signifie simplement que Babel lui-même ne fonctionnera pas sur les anciennes versions de Node. Il peut toujours produire du code qui s'exécute sur d'anciennes versions de Node.

Changements de recherche de configuration

Pour plus d'informations, lisez notre comparaison 6.x vs 7.x.

Babel rencontrait précédemment des problèmes avec node_modules, les liens symboliques et les monorepos. Nous avons apporté des modifications : Babel s'arrêtera à la limite du package.json au lieu de remonter la chaîne. Pour les monorepos, nous avons ajouté un fichier babel.config.js centralisant la configuration (ou une config par package). La version 7.1 introduit l'option rootMode pour des recherches supplémentaires si nécessaire.

Dépréciation des préréglages annuels

Le préréglage "env" existe depuis plus d'un an et remplace complètement certains préréglages précédemment recommandés.

  • babel-preset-es2015

  • babel-preset-es2016

  • babel-preset-es2017

  • babel-preset-latest

  • Une combinaison des éléments ci-dessus ^

Ces préréglages doivent être remplacés par "env".

Dépréciation des préréglages stage

Nous supprimons les préréglages stage au profit d'une utilisation explicite des propositions. Consultez le README stage-0 pour les étapes de migration.

Pour automatiser cette opération, exécutez npx babel-upgrade (PR ajouté ici).

Suppression des polyfills de propositions dans @babel/polyfill

Suivant la même logique, nous avons retiré les polyfills de propositions de @babel/polyfill.

Actuellement, @babel/polyfill est principalement un alias de core-js v2. Source

Auparavant, il s'agissait simplement de 2 imports :

JavaScript
import "core-js/shim"; // included < Stage 4 proposals
import "regenerator-runtime/runtime";

Si vous souhaitez utiliser des propositions, vous devrez les importer indépendamment. Importez-les directement depuis le package core-js ou un autre package npm.

Par exemple :

JavaScript
// for core-js v2:
import "core-js/fn/array/flat-map";

// for core-js v3:
import "core-js/features/array/flat-map";

Voici la liste des polyfills de propositions Stage < 3 dans core-js v2 :

Details
JavaScript
// core-js v2

// Stage 3
import "core-js/fn/string/trim-left";
import "core-js/fn/string/trim-right";
import "core-js/fn/string/match-all";
import "core-js/fn/array/flat-map";
import "core-js/fn/array/flatten"; // RENAMED
import "core-js/fn/global";

// Stage 1
import "core-js/fn/symbol/observable";
import "core-js/fn/promise/try";
import "core-js/fn/observable";

// Stage 1 Math Extensions
import "core-js/fn/math/clamp";
import "core-js/fn/math/deg-per-rad";
import "core-js/fn/math/degrees";
import "core-js/fn/math/fscale";
import "core-js/fn/math/iaddh";
import "core-js/fn/math/isubh";
import "core-js/fn/math/imulh";
import "core-js/fn/math/rad-per-deg";
import "core-js/fn/math/radians";
import "core-js/fn/math/scale";
import "core-js/fn/math/umulh";
import "core-js/fn/math/signbit";

// Stage 1 "of and from on collection constructors"
import "core-js/fn/map/of";
import "core-js/fn/set/of";
import "core-js/fn/weak-map/of";
import "core-js/fn/weak-set/of";
import "core-js/fn/map/from";
import "core-js/fn/set/from";
import "core-js/fn/weak-map/from";
import "core-js/fn/weak-set/from";

// Stage 0
import "core-js/fn/string/at";

// Nonstandard
import "core-js/fn/object/define-getter";
import "core-js/fn/object/define-setter";
import "core-js/fn/object/lookup-getter";
import "core-js/fn/object/lookup-setter";
// import "core-js/fn/map/to-json"; // Not available standalone
// import "core-js/fn/set/to-json"; // Not available standalone

import "core-js/fn/system/global";
import "core-js/fn/error/is-error";
import "core-js/fn/asap";

// Decorator metadata? Not sure of stage/proposal
import "core-js/fn/reflect/define-metadata";
import "core-js/fn/reflect/delete-metadata";
import "core-js/fn/reflect/get-metadata";
import "core-js/fn/reflect/get-metadata-keys";
import "core-js/fn/reflect/get-own-metadata";
import "core-js/fn/reflect/get-own-metadata-keys";
import "core-js/fn/reflect/has-metadata";
import "core-js/fn/reflect/has-own-metadata";
import "core-js/fn/reflect/metadata";

Gestion des versions/dépendances

La plupart des plugins/packages de premier niveau ont désormais une peerDependency sur @babel/core.

Renommages des packages

  • babylon devient @babel/parser

Vous pouvez toujours utiliser la version raccourcie des noms de packages (supprimer preset- ou plugin-) dans la configuration, mais par souci de clarté je préfère utiliser le nom complet (peut-être devrions-nous simplement abandonner cette pratique, car elle n'économise pas tant de frappe).

{
- "presets": ["@babel/preset-react"],
+ "presets": ["@babel/react"], // this is equivalent
- "plugins": ["@babel/transform-runtime"],
+ "plugins": ["@babel/plugin-transform-runtime"], // same
}

Packages scopés

Le changement majeur est le passage définitif à des packages scopés (les noms de dossiers dans le monorepo restent inchangés mais le nom dans le package.json est modifié).

Cela élimine les conflits de noms accidentels ou intentionnels, sépare clairement des plugins communautaires et simplifie la convention de nommage.

Vos dépendances doivent être modifiées ainsi :

babel-cli@babel/cli. Globalement, nous avons remplacé babel- par @babel/.

Usage dans la configuration

Vous pouvez toujours utiliser la notation raccourcie pour les presets ou plugins. Cependant, à cause du passage aux packages scopés, vous devez spécifier @babel/ comme vous le feriez pour un preset personnalisé.

babel.config.js
module.exports = {
presets: ["@babel/env"], // "@babel/preset-env"
plugins: ["@babel/transform-arrow-functions"], // same as "@babel/plugin-transform-arrow-functions"
};

Passage à -proposal- pour les propositions TC39

Tout plugin n'appartenant pas à une release annuelle (ES2015, ES2016, etc.) doit être renommé avec -proposal. Cela indique clairement qu'une proposition n'est pas officiellement dans JavaScript.

Exemples :

  • @babel/plugin-transform-function-bind devient @babel/plugin-proposal-function-bind (Stage 0)

  • @babel/plugin-transform-class-properties devient @babel/plugin-proposal-class-properties (Stage 3)

Cela implique qu'une proposition passant au Stage 4 nécessitera un renommage du package.

Suppression de l'année dans les noms de packages

Certains plugins contenaient -es3- ou -es2015- dans leur nom, ce qui était superflu.

@babel/plugin-transform-es2015-classes est devenu @babel/plugin-transform-classes.

"use strict" et this dans CommonJS

Dans Babel 6, les transformations ES6 modifiaient systématiquement tous les fichiers traités, sans vérifier la présence effective d'imports/exports ES6. Cela remplaçait les références à this au niveau fichier par undefined et ajoutait "use strict" en tête de tous les modules CommonJS traités par Babel.

JavaScript
// input.js
this;
JavaScript
// output.js v6
"use strict"; // assumed strict modules
undefined; // changed this to undefined
JavaScript
// output.js v7
this;

Cette fonctionnalité a été restreinte dans Babel 7 : pour la transformation transform-es2015-modules-commonjs, le fichier n'est modifié que s'il contient des imports ou exports ES6. (Note de l'éditeur : Cela pourrait changer à nouveau si nous intégrons https://github.com/babel/babel/issues/6242, nous devrons donc revoir cela avant publication).

JavaScript
// input2.js
import "a";
JavaScript
// output.js v6 and v7
"use strict";
require("a");

Si vous comptiez sur Babel pour injecter automatiquement "use strict" dans tous vos modules CommonJS, vous devrez explicitement utiliser le plugin transform-strict-mode dans votre configuration Babel.

Séparation des presets React et Flow

babel-preset-react incluait toujours le plugin flow. Cela causait de nombreux problèmes lorsque des utilisateurs employaient accidentellement la syntaxe flow suite à une faute de frappe, ou l'ajoutaient sans vérification de types via flow lui-même, générant ainsi des erreurs.

Ce problème s'est amplifié avec le support de TypeScript. Pour utiliser simultanément les presets React et TypeScript, il aurait fallu trouver un moyen d'activer/désactiver automatiquement la syntaxe via le type de fichier ou une directive. Finalement, séparer complètement les presets s'est avéré plus simple.

Les presets permettent à Babel d'analyser les types fournis par Flow/TypeScript (et autres dialectes/langages), puis de les supprimer lors de la compilation en JavaScript.

{
- "presets": ["@babel/preset-react"]
+ "presets": ["@babel/preset-react", "@babel/preset-flow"] // parse & remove flow types
+ "presets": ["@babel/preset-react", "@babel/preset-typescript"] // parse & remove typescript types
}

Analyse des options

Les options de configuration de Babel sont plus strictes qu'en version 6. L'utilisation de listes séparées par des virgules pour les presets (ex: "presets": 'es2015, es2016') fonctionnait auparavant mais échouera désormais et doit être remplacée par un tableau #5463.

Notez que cela ne s'applique pas à la CLI, où --presets es2015,es2016 continuera de fonctionner.

{
- "presets": "@babel/preset-env, @babel/preset-react"
+ "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Exports des plugins/presets

Tous les plugins/presets doivent désormais exporter une fonction plutôt qu'un objet pour plus de cohérence (via babel/babel#6494). Cela facilitera la mise en cache.

Résolution des valeurs de configuration basées sur des chaînes

Dans Babel 6, les valeurs passées directement à Babel (hors fichier de configuration) étaient résolues relativement aux fichiers compilés, causant beaucoup de confusion.

Dans Babel 7, les valeurs sont résolues de manière cohérente soit relativement au fichier de configuration qui les charge, soit relativement au répertoire de travail.

Pour les valeurs presets et plugins, ce changement signifie que la CLI se comportera correctement dans des cas comme :

Shell
babel --presets @babel/preset-env ../file.js

Si votre dossier node_modules est dans ., Babel 6 échouait car le preset n'était pas trouvable.

Ce changement affecte aussi only et ignore, comme détaillé ci-après.

Modèles only et ignore basés sur des chemins

Dans Babel 6, only et ignore étaient traités comme des chaînes de correspondance génériques plutôt que comme des globs de chemins. Par exemple, *.foo.js correspondait à ./**/*.foo.js, ce qui était déroutant.

Dans Babel 7, ils sont désormais traités comme des modèles glob basés sur des chemins (relatifs ou absolus). Si vous utilisiez ces modèles, vous devrez probablement ajouter un préfixe **/ pour garantir une correspondance récursive.

Les modèles only et ignore fonctionnent toujours pour les répertoires : only: './tests' compile uniquement les fichiers du dossier tests, sans nécessiter **/*.js pour les fichiers imbriqués.

Commandes CLI de Babel

L'argument --copy-files de la commande babel, qui demande à Babel de copier tous les fichiers d'un répertoire qu'il ne sait pas traiter, copiera désormais aussi les fichiers échouant aux vérifications only/ignore, alors qu'auparavant il ignorait silencieusement tous les fichiers exclus.

@babel/node

La commande babel-node dans Babel 6 faisait partie du paquet babel-cli. Dans Babel 7, cette commande a été déplacée vers son propre paquet @babel/node. Si vous utilisez cette commande, vous devrez ajouter cette nouvelle dépendance.

@babel/runtime, @babel/plugin-transform-runtime

Nous avons séparé les helpers de Babel de son comportement de "polyfill" dans le runtime. Plus de détails dans la PR.

@babel/runtime ne contient désormais que les helpers. Si vous avez besoin de core-js, utilisez @babel/runtime-corejs2 avec l'option correspondante dans la transformation. Dans les deux cas, vous aurez toujours besoin de @babel/plugin-transform-runtime.

Uniquement les helpers

Shell
# install the runtime as a dependency
npm install @babel/runtime
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
babel.config.json
{
"plugins": ["@babel/plugin-transform-runtime"]
}

Helpers + polyfill de core-js

Si vous avez besoin du support core-js avec transform-runtime, passez désormais l'option corejs et utilisez la dépendance @babel/runtime-corejs2 au lieu de @babel/runtime.

Shell
# install the runtime as a dependency
npm install @babel/runtime-corejs2
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
{
"plugins": [
- ["@babel/plugin-transform-runtime"],
+ ["@babel/plugin-transform-runtime", {
+ "corejs": 2,
+ }],
]
}

Conformité aux spécifications

@babel/plugin-proposal-object-rest-spread

Une virgule finale ne peut pas suivre un RestElement dans les objets #290 medium

var {
- ...y, // trailing comma is a SyntaxError
+ ...y
} = { a: 1 };

Étant donné que Object Spread définit de nouvelles propriétés tandis qu'Object.assign les définit simplement, Babel a modifié son comportement par défaut pour mieux respecter les spécifications.

JavaScript
// input
z = { x, ...y };
JavaScript
// v7 default behavior: ["proposal-object-rest-spread"]
function _objectSpread(target) { ... }

z = _objectSpread({
x
}, y);
JavaScript
// Old v6 behavior: ["proposal-object-rest-spread", { "loose": true }]
function _extends(target) { ... }

z = _extends({
x
}, y);
JavaScript
// Substitute for Object.assign: ["proposal-object-rest-spread", { "loose": true, "useBuiltIns": true }]
z = Object.assign(
{
x,
},
y
);

@babel/plugin-proposal-class-properties

Le comportement par défaut est désormais aligné sur ce qui était précédemment le mode "spec".

JavaScript
// input
class Bork {
static a = "foo";
y;
}
JavaScript
// v7 default behavior: ["@babel/plugin-proposal-class-properties"]
var Bork = function Bork() {
Object.defineProperty(this, "y", {
enumerable: true,
writable: true,
value: void 0,
});
};

Object.defineProperty(Bork, "a", {
enumerable: true,
writable: true,
value: "foo",
});
JavaScript
// old v6 behavior: ["@babel/plugin-proposal-class-properties", { "loose": true }]
var Bork = function Bork() {
this.y = void 0;
};

Bork.a = "foo";

Scission de @babel/plugin-transform-export-extensions en deux propositions renommées

Ce changement était attendu depuis longtemps et a finalement été implémenté.

@babel/plugin-proposal-export-default-from

JavaScript
export v from "mod";

@babel/plugin-proposal-export-namespace-from

JavaScript
export * as ns from "mod";

@babel/plugin-transform-template-literals

Mise à jour de la révision des Template Literals #5523 low

Consultez la proposition pour la révision des Template Literals.

Cela provoquait dans Babel 6 l'erreur Bad character escape sequence (5:6).

JavaScript
tag`\unicode and \u{55}`;

Ce problème a été corrigé dans Babel 7, qui génère désormais un résultat similaire à :

JavaScript
// default
function _taggedTemplateLiteral(strings, raw) {
return Object.freeze(
Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })
);
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteral(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);
JavaScript
// loose mode
function _taggedTemplateLiteralLoose(strings, raw) {
strings.raw = raw;
return strings;
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteralLoose(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);

Retour au mode "spec" précédent pour les template literals classiques

JavaScript
// input
`foo${bar}`;
JavaScript
// default v7 behavior: ["@babel/plugin-transform-template-literals"]
"foo".concat(bar);
JavaScript
// old v6 behavior: ["@babel/plugin-transform-template-literals", { "loose": true }]
"foo" + bar;

@babel/plugin-proposal-decorators

En prévision de la nouvelle implémentation de la proposition de décorateurs, nous avons décidé d'en faire le comportement par défaut. Cela signifie que pour continuer à utiliser la syntaxe/comportement actuel des décorateurs, vous devez définir l'option legacy à true.

 {
"plugins": [
- "@babel/plugin-proposal-decorators"
+ ["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}

NOTE : Si vous utilisez @babel/preset-stage-0 ou @babel/preset-stage-1 (qui incluent ce plugin), vous devez leur passer l'option decoratorsLegacy.

@babel/plugin-proposal-pipeline-operator

Les nouvelles propositions instables généreront désormais une erreur par défaut et nécessiteront que chacun adopte explicitement une proposition spécifique tant qu'elles sont encore en deçà du stade 2. Ce point est détaillé dans ce billet.

{
"plugins": [
- "@babel/plugin-proposal-pipeline-operator"
+ ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]
]
}

Suppression de babel-plugin-transform-class-constructor-call

babel-plugin-transform-class-constructor-call a été supprimé #5119 faible

Le comité TC39 a abandonné cette proposition. Vous pouvez déplacer votre logique dans le constructeur ou dans une méthode statique.

Voir /docs/plugins/transform-class-constructor-call/ pour plus d'informations.

  class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}

- call constructor(x, y) {
+ static secondConstructor(x, y) {
return new Point(x, y);
}
}

let p1 = new Point(1, 2);
- let p2 = Point(3, 4);
+ let p2 = Point.secondConstructor(3, 4);

@babel/plugin-async-to-generator

Nous avons fusionné babel-plugin-transform-async-to-module-method dans le plugin async standard en le transformant simplement en option.

{
"plugins": [
- ["@babel/transform-async-to-module-method"]
+ ["@babel/transform-async-to-generator", {
+ "module": "bluebird",
+ "method": "coroutine"
+ }]
]
}

babel

Suppression du package babel #5293 low

Ce package affiche actuellement un message d'erreur vous invitant à installer babel-cli dans la v6. Nous pensons cependant pouvoir proposer une utilisation intéressante de ce nom.

@babel/register

babel-core/register.js a été supprimé #5132 low

L'utilisation dépréciée de babel-core/register a été supprimée dans Babel 7 ; utilisez plutôt le package autonome @babel/register.

Installez @babel/register comme nouvelle dépendance :

npm install --save-dev @babel/register

Mise à niveau avec Mocha :

- mocha --require babel-core/register
+ mocha --require @babel/register

@babel/register ne compilera désormais que les fichiers du répertoire de travail courant (modification apportée pour résoudre les problèmes de liens symboliques).

Les options de @babel/register sont maintenant remplacées plutôt que fusionnées.

@babel/generator

Suppression de l'option quotes #5154] none

Si vous souhaitez formater la sortie compilée, utilisez recast/prettier/escodegen ou forkez babel-generator.

Cette option n'était disponible que via babel-generator explicitement jusqu'à la v6.18.0 où nous avons exposé parserOpts et generatorOpts. Un bogue dans cette version ayant empêché son utilisation dans Babel, personne n'aurait dû l'utiliser.

Suppression de l'option flowUsesCommas #5123 none

Actuellement, deux syntaxes sont prises en charge (, et ;) pour les types d'objets Flow.

Ce changement fait simplement que babel-generator produit , au lieu de ;.

@babel/core

Suppression de babel-core/src/api/browser.js #5124 none

babel-browser avait déjà été supprimé dans la version 6.0. Si vous devez utiliser Babel dans le navigateur ou un environnement non-Node, utilisez @babel/standalone.

Babel renverra désormais filename sous forme de chemin absolu #8044

@babel/preset-env

Le mode loose exclura désormais automatiquement la transformation typeof-symbol (beaucoup de projets utilisant le mode loose faisaient cela).