Aller au contenu principal

Version 5.0.0 publiée

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

Ces derniers mois, Babel a été adopté par plusieurs grandes communautés comme Node, React, Ember, Backbone, Angular, Rails et bien d'autres. Nous avons lancé la page Utilisateurs il y a seulement quelques semaines, et c'est vraiment impressionnant de voir tous ceux qui l'utilisent. Des entreprises comme CloudFlare, Netflix, Mozilla et Yahoo!. Des projets comme Ghost, Atom, Mapbox, et bien d'autres encore.

Nous avons vu d'innombrables articles de blog, conférences, événements et cours sur ES6+ utilisant Babel, et les outils officiels de Babel ont été téléchargés près de 2 millions de fois.

Aujourd'hui, nous publions de loin la plus grande version de Babel jamais réalisée.

Si vous effectuez une mise à jour depuis Babel 4.x, veuillez consulter les changements cassants.

Cette version inclut les nouvelles propositions ES7 :

L'ensemble du pipeline interne de traversée et de transformation a été réécrit, ce qui améliore considérablement la flexibilité et permettra de nombreuses optimisations futures des performances du pipeline.

Cette version introduit également une API de plugin, permettant aux utilisateurs d'intégrer leurs propres transformateurs personnalisés pour exploiter les puissants mécanismes de transformation offerts par Babel.

Vous pouvez consulter le CHANGELOG complet ici.

Et comme toujours, si vous rencontrez des régressions, merci de les signaler immédiatement.

Processus TC39

Dans cette version, vous constaterez notre alignement avec le processus TC39. Le TC39 est le comité technique d'ECMA chargé de rédiger le standard ECMAScript. Leur processus est catégorisé en 5 étapes :

  • Étape 0 - Ébauche préliminaire (Strawman)

  • Étape 1 - Proposition

  • Étape 2 - Brouillon

  • Étape 3 - Candidat

  • Étape 4 - Finalisée

Les propositions de l'étape 2 ou supérieure sont activées par défaut dans Babel. Cela ne signifie pas qu'elles seront nécessairement incluses dans les futures spécifications ECMAScript ou même dans Babel lui-même. L'étape 2 est considérée comme un bon point pour l'inclusion par défaut dans Babel en raison de leur maturité relative et du besoin de retours critiques sur les propositions.

Plongeons maintenant dans les changements apportés à la version 5.0.


Sommaire :

New Features

Nouvelles propositions

Stage 0 : Class Properties

La proposition stage 0 de Jeff Morrison sur les initialiseurs de propriétés de classe comble le manque de composition de propriétés dans les classes. Cela correspond à l'exemple des propriétés de classe mentionné dans l'annonce de React 0.13 beta.

Exemple :

JavaScript
class Person {
firstName = "Sebastian";
static lastName = "McKenzie";
}

assert(new Person().firstName, "Sebastian");
assert(Person.lastName, "McKenzie");

Utilisation :

JavaScript
require("babel").transform("code", {
optional: ["es7.classProperties"]
});
// or
require("babel").transform("code", { stage: 0 });
Shell
$ babel --optional es7.classProperties script.js
# or
$ babel --stage 0 script.js

Stage 1 : Decorators

La proposition stage 1 de Yehuda Katz sur les décorateurs permet de composer élégamment des descripteurs de propriétés et des métadonnées décoratives. À terme, cela permettra de représenter facilement le puissant modèle objet d'Ember avec des classes natives.

Exemple :

JavaScript
function concat(...args) {
let sep = args.pop();

return function(target, key, descriptor) {
descriptor.initializer = function() {
return args.map(arg => this[arg]).join(sep);
}
}
}

function autobind(target, key, descriptor) {
var fn = descriptor.value;
delete descriptor.value;
delete descriptor.writable;
descriptor.get = function () {
var bound = fn.bind(this);
Object.defineProperty(this, key, {
configurable: true,
writable: true,
value: bound
});
return bound;
};
}

class Person {
firstName = "Sebastian";
lastName = "McKenzie";

@concat("firstName", "lastName", " ") fullName;
@concat("lastName", "firstName", ", ") formalName;

@autobind
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}

assert(new Person().fullName, "Sebastian McKenzie");
assert(new Person().formalName, "McKenzie, Sebastian");
assert(new Person().getFullName.call(null), "Sebastian McKenzie");

Utilisation :

JavaScript
require("babel").transform("code", {
optional: ["es7.decorators"]
});
// or
require("babel").transform("code", { stage: 1 });
Shell
$ babel --optional es7.decorators script.js
# or
$ babel --stage 1 script.js

Stage 1 : Export Extensions

La proposition stage 1 de Lee Byron sur les instructions d'exportation supplémentaires achève la symétrie entre les instructions import et export, vous permettant d'exporter facilement des espaces de noms et des exports par défaut depuis des modules externes sans modifier la portée locale.

Exporter un default

JavaScript
export foo from "bar";

équivalent à :

JavaScript
import _foo from "bar";
export { _foo as foo };

Exporter un namespace

JavaScript
export * as ns from "mod";

équivalent à :

JavaScript
import * as _ns from "mod";
export { _ns as ns };

Utilisation :

JavaScript
require("babel").transform("code", {
optional: ["es7.exportExtensions"]
});
// or
require("babel").transform("code", { stage: 1 });
Shell
$ babel --optional es7.exportExtensions script.js
# or
$ babel --stage 1 script.js

Optimisations React

En préparation de React 0.14, Babel prend en charge certains transformateurs d'optimisation pour JSX.

Éléments constants

À partir de la version 0.14, les ReactElements et leurs objets props peuvent être traités comme des types valeur. C'est-à-dire que toute instance est conceptuellement équivalente si toutes leurs valeurs sont identiques.

Prenons cet exemple de fonction :

JavaScript
import React from "react";

function render() {
return <div className="foo" />;
}

On peut l'optimiser en déplaçant le JSX hors du corps de la fonction, afin que la même instance soit retournée à chaque appel :

JavaScript
import React from "react";

var _ref = <div className="foo" />;

function render() {
return _ref;
}

Cela permet non seulement de réutiliser les mêmes objets, mais React interrompra automatiquement toute réconciliation des composants constants - sans shouldComponentUpdate manuel.

Utilisation :

JavaScript
require("babel").transform("code", {
optional: ["optimisation.react.constantElements"]
});
Shell
$ babel --optional optimisation.react.constantElements script.js

Éléments inline

Production uniquement

Les éléments inline doivent only être activés en production car plusieurs messages d'avertissement React sont supprimés, ce qui est très risqué en développement.

À partir de React 0.14, les ReactElements peuvent être inlinés :

JavaScript
<div className="foo">{bar}<Baz key="baz" /></div>

sous forme d'objets :

JavaScript
{ type: 'div', props: { className: 'foo', children:
[ bar, { type: Baz, props: { }, key: 'baz', ref: null } ]
}, key: null, ref: null }

Cela améliore les performances par rapport à l'appel existant React.createElement en inlinant son résultat.

Utilisation :

JavaScript
require("babel").transform("code", {
optional: ["optimisation.react.inlineElements"]
});
Shell
$ babel --optional optimisation.react.inlineElements script.js

.babelrc

Babel 5.0.0 prend désormais en charge .babelrc nativement dans l'ensemble de ses intégrations. Cela signifie qu'il fonctionnera avec babel/register, babel-node ainsi qu'avec toute la gamme de plugins de build systems et de module loaders comme babel-loader, babelify, et autres.

.babelrc est l'équivalent de .jshintrc pour JSHint et .jscsrc pour JSCS.

JSON
{
"stage": 1,
"ignore": [
"foo.js",
"bar/**/*.js"
]
}

Consultez la documentation pour plus d'informations.

API de plugins

La version 5.0.0 introduit également l'API de plugins tant attendue. Elle vous permet d'interagir avec les puissants mécanismes internes de traversée et transformation de Babel. Voir la documentation pour plus d'informations.

Breaking Changes

Option expérimentale

L'option experimental a été supprimée. Pas d'inquiétude cependant : un remplacement existe. Babel classe désormais les transformateurs ES7 selon les stades TC39.

En bref : si vous utilisiez l'option experimental, remplacez-la simplement par $ babel --stage 0 ou { stage: 0 }.

Rappel : Les propositions de stade 2 ou supérieur sont activées par défaut.

Stade 0

  • es7.classProperties

  • es7.comprehensions

Stade 1

  • es7.asyncFunctions

  • es7.decorators

  • es7.exportExtensions

  • es7.objectRestSpread

Stade 2 (activé par défaut, comme les stades supérieurs)

  • es7.exponentiationOperator

Pour la liste complète des propositions ES7 actuelles, consultez le dépôt tc39/ecma262.

Option returnUsedHelpers

L'option returnUsedHelpers a été renommée en metadataUsedHelpers et le résultat retourné a été modifié de usedHelpers à metadata.usedHelpers.

Changements relatifs aux classes

La version 5.0.0 introduit des sémantiques mises à jour pour les classes dérivées, attendues depuis longtemps.

super() doit être appelé dans le constructeur d'une classe dérivée.

JavaScript
class Foo extends Bar {
constructor() {
// no `super();`
}
}

L'accès à this avant super() dans un constructeur de classe dérivée est interdit.

JavaScript
class Foo extends Bar {
constructor() {
this.foo; // `this` access before `super();`
super();
}
}

super() est uniquement autorisé dans les constructeurs de classes dérivées.

JavaScript
class Foo {
constructor() {
super(); // not in a derived constructor
}
}

Fonctionnalités supprimées

  • Le playground a été retiré pour concentrer le développement sur les fonctionnalités ES principales et les propositions officielles. Cela réduit aussi les risques de conflits syntaxiques empêchant l'implémentation de fonctionnalités standards.

  • Les références abstraites ont été supprimées car la proposition a été remplacée. Le support d'une ou plusieurs des nouvelles propositions pourrait être implémenté à l'avenir.


Pour conclure, nous espérons que cette version vous enthousiasme autant que nous. Beaucoup d'efforts y ont été consacrés, et nous croyons qu'elle nous positionne durablement pour l'avenir.

— The Babel team

Les imports sont désormais hoistés

Dans la version 4.x, les imports étaient placés à l'endroit où ils apparaissaient dans le code. Ce qui signifie que ce code :

global.test = 'test'
import './test'

serait compilé en :

'use strict';

global.test = 'test';
require('./test');

Cependant, à partir de la version 5.x, ce comportement a été modifié afin de se conformer à la spécification ES6 et les importations seront désormais hoistées. Concrètement, cela signifie que l'extrait de code ci-dessus sera transformé en quelque chose comme :

'use strict';

require('./test');
global.test = 'test';

Si votre code nécessitait l'exécution de certaines opérations pendant l'importation d'un module spécifique - ce qui pourrait être le cas lors de tests où vous devez simuler des propriétés de window :) - vous devriez extraire ces opérations dans un fichier dédié et l'importer avant le code qui en dépend.