Babili (babel-minify)
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 →
Nous avons publié Babili en version bêta (0.0.1) il y a quelques jours sous licence MIT !
Testez-le dans le REPL de Babel et signalez tout bug ou optimisation potentielle ! Rejoignez également le salon Slack #minify !
De nombreuses questions (légitimes) se posent sur l'utilité d'un nouveau minificateur, ce billet vise à y répondre.
En bref : Babili accepte du code ES2015+ en entrée, alors que les minificateurs actuels se limitent à ES5, nécessitant une transpilation préalable. Cela devient superflu avec l'envoi d'ES2015 aux clients. Babili est modulaire/flexible (étant un préset Babel, il supporte les plugins utilisateur) et utilisable comme préset ou outil CLI. Il pourra aussi réaliser des optimisations spécifiques à ES2015+.
Prononciation
# sounds like "bah billy" or "Babadi" (from DBZ)
say Babili
Babili signifie Babylone en akkadien.
Si le nom est difficile à retenir, babel-minify fonctionne aussi (un problème existe sur le nom).
Pourquoi minifier ?
Fondamentalement, la minification supprime les caractères superflus sans altérer la fonctionnalité : commentaires, espaces, sauts de ligne et parenthèses excédentaires. La minification avancée transforme les programmes en équivalents plus compacts et élimine le code redondant/inaccessible.
La minification réduit principalement la taille du payload JavaScript serveur-client : les utilisateurs téléchargent moins de code. Elle peut aussi accélérer le parsing (moins de code à analyser) et parfois l'exécution (ex: optimisations avancées comme l'inlining de fonctions).
Minificateurs actuels
Des outils comme Uglify ne supportent pas encore les dernières versions d'ECMAScript (pas encore : branche harmony).
Nous utilisons actuellement Babel pour transpiler le code ES2015 vers ES5 afin de supporter les anciens navigateurs. Puis des outils comme Uglify réduisent la taille du bundle.
Avec l'implémentation croissante d'ES2015 dans les navigateurs et l'abandon des anciennes versions, la cible ECMAScript évolue. Mais comme Uglify ne peut parser ES2015+, une transpilation vers ES5 reste nécessaire.
Babili
C'est là qu'intervient Babili.
Babili comprend ES2015+ car il utilise la chaîne d'outils Babel.
Implémenté comme un ensemble de plugins Babel, il s'utilise via le préset babili.
Exemple
Supposons que nous ciblions les dernières versions de Chrome, Firefox, Edge et Safari – toutes supportent les classes ES2015. Transpiler ces classes vers des fonctions constructeurs et méthodes prototype (ES5) génère plus de code (et risque d'annuler les optimisations navigateur dédiées aux classes).
class Mangler {
constructor(program) {
this.program = program;
}
}
// need this since otherwise Mangler isn't used
new Mangler();
Auparavant, nous pouvions exécuter Babel pour transformer la classe en une fonction puis appliquer Uglify sur le code compilé avant l'envoi au navigateur.
// ES2015 code -> Babel -> Uglify/Babili -> Minified ES5 Code
var a=function a(b){_classCallCheck(this,a),this.program=b};a();
Avec Babili, vous pouvez simplement exécuter le minifieur qui fonctionne directement sur du code ES2015.
// ES2015 code -> Babili -> Minified ES2015 Code
class a{constructor(b){this.program=b}}new a;
Il est également important de noter que cette approche ne se limite pas à ES2015. Comme Babel évolue avec ECMAScript (ES2015, ES2016 et maintenant ES2017) et suit le processus des propositions pour les fonctionnalités expérimentales (via nos presets stage-x), le minifieur devrait pouvoir générer n'importe quelle version d'ECMAScript prise en charge.
À l'avenir, nous pourrions exploiter les informations syntaxiques ES2015+ disponibles à la compilation (par exemple, savoir qu'une fonction est une fonction fléchée ou qu'une liaison a une portée de bloc) pour réaliser des optimisations avancées. Nous pourrons également exploiter créativement le ciblage d'environnements ES2015+.
Nous ne faisons que commencer, alors faites-nous part de vos idées !
Quelques plugins
Pour illustrer certaines transformations :
babel-plugin-minify-constant-folding :
Tente d'évaluer les expressions et d'inliner les résultats. Ne traite actuellement que les nombres et chaînes de caractères.
2 * 3;
"b" + a + "c" + "d" + g + z + "f" + "h" + "z"
6;
"b" + a + "cd" + g + z + "fhz";
babel-plugin-minify-mangle-names :
Renommage de variables prenant en compte le contexte et la portée.
var globalVariableName = 42;
function foo() {
var longLocalVariableName = 1;
if (longLocalVariableName) {
console.log(longLocalVariableName);
}
}
var globalVariableName = 42;
function foo() {
var a = 1;
if (a) {
console.log(a);
}
}
Utilisation
Preset Babel
Si vous utilisez déjà Babel, ajoutez simplement le preset babili (babel-preset-babili) à votre configuration.
Activez-le uniquement en production via l'option env utilisant process.env.BABEL_ENV ou process.env.NODE_ENV.
$ npm install babel-preset-babili --save-dev
// previous .babelrc
{ "presets": ["es2015"] }
// .babelrc
{
"presets": ["es2015"],
"env": {
"production": {
"presets": ["babili"]
}
}
}
Un inconvénient de l'utilisation de Babili comme preset est son exécution fichier par fichier plutôt que sur le bundle complet. La minification intervient généralement après le bundling (ex: "UglifyJsPlugin" dans webpack). Cependant, cette exécution post-bundling annulerait les gains de vitesse (à mesurer) de l'étape combinée transpilation/minification. C'est un point nécessitant réflexion : comment mieux intégrer ou transmettre des informations au bundler.
CLI Babili
Sans Babel, utilisez notre outil CLI autonome babili (actuellement un wrapper pour babel-cli + le preset). Exécutez-le après transpilation (ou non) en remplacement d'Uglify.
$ npm install babili --save-dev
$ babili src -d lib
# equivalent to
# babel src -d lib --presets=babili --no-babelrc
Webpack
Utilisez simplement le preset avec babel-loader.
$ npm install babel-core babel-loader babel-preset-babili
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: {
presets: ['babili']
}
}
]
}
Ou utilisez-le séparément avec le babili-webpack-plugin (développé par @boopathi, contributeur de Babili).
$ npm install babili-webpack-plugin --save-dev
// webpack.config.js
const BabiliPlugin = require("babili-webpack-plugin");
module.exports = {
entry: //...,
output: //...,
plugins: [
new BabiliPlugin(options)
]
}
Nous visons une meilleure intégration avec Webpack/les bundlers prochainement ! Voir aussi #100.
Avantages/Inconvénients
Avantages d'Uglify
-
Aucune modification nécessaire de votre chaîne d'outils existante si vous minifiez déjà.
-
Testé en conditions réelles/prêt pour la production (il existe depuis des années et bénéficie d'une large adoption (nous l'utilisons tous) !
-
Il est extrêmement rapide et produit déjà un code compact.
Inconvénients d'Uglify
-
Parser et outils personnalisés, ce qui complique la sortie/minification d'ES2015+ et les modifications.
-
Non modulaire, et aucune possibilité actuelle de créer ses propres plugins ou stratégies de minification en dehors du cœur.
Avantages de Babili :
-
Compatible ES2015+ (aucun traitement spécial requis grâce à l'utilisation du parser Babylon) et Babel évoluera avec les standards/navigateurs.
-
Utilise la chaîne d'outils existante de Babel, utilisable comme preset Babel ou en standalone.
-
Potentiel pour des transformations intelligentes personnalisées (React/Flow, etc.).
-
Peut exploiter les annotations Flow/TypeScript pour activer une minification avancée.
-
Chaque étape de minification peut être divisée en plugin indépendant, avec de nombreuses options de personnalisation. Cela facilite les contributions et le signalement des problèmes spécifiques. Les utilisateurs peuvent créer leurs propres plugins expérimentaux avant leur intégration officielle.
- Exemple : ce plugin transforme simplement
trueen!0– une implémentation simple.
- Exemple : ce plugin transforme simplement
-
Transition aisée pour les utilisateurs familiers avec la transpilation via Babel.
Inconvénients de Babili :
-
Publication précoce, donc peu d'utilisateurs actuellement. Les early adopters devront utiliser un outil moins éprouvé qu'Uglify initialement.
-
Actuellement, les performances et la taille du code sont inférieures à Uglify sur nos tests de référence. C'est un axe d'amélioration prioritaire.
TL;DR : Babili pourra suivre l'évolution du standard ECMAScript et cibler les environnements requis. Son potentiel est important : bien que moins mature qu'Uglify actuellement (sortie récente), les optimisations progressives avec l'usage le rendront compétitif.
Comment contribuer
Amjad travaillait sur ce projet depuis un moment, mais nous avons décidé de le publier plus tôt en version bêta pour permettre à la communauté de le tester et de contribuer via signalements de bugs et correctifs.
Le projet en est à ses débuts – l'aide est bienvenue ! Notre priorité est désormais de stabiliser Babili pour une version 1.0.0.
Nous travaillerons à atteindre la vitesse et la compacité de code d'Uglify/Closure Compiler en mode simple.
-
Tests sur davantage de codebases : Crucial pour tous. Un minificateur traitant tout le code, les cas limites/bugs non couverts par nos tests unitaires sont probables. Nous souhaitons simplifier le signalement des problèmes ; le support dans le REPL facilitera la reproduction des bugs. À terme, des options d'activation par plugin permettront des reproductions minimales.
-
Infrastructure/maintenance du projet : Mise en place de benchmarks robustes et de tests d'intégration sur des projets open-source populaires (exécution du minificateur puis des tests unitaires du projet).
-
Vérifier la sortie : Si une simplification est possible, créez simplement une issue suggérant une nouvelle transformation ou un nouveau plugin. La modularité permet aussi de développer ses propres plugins avant leur intégration éventuelle dans le preset principal.
Un immense merci à Amjad (@amasad) pour avoir lancé ce projet, et à Facebook de nous avoir permis de le publier sous l'organisation Babel avec une licence MIT ! Sebastian (@kittens) a évidemment joué un rôle majeur, car ce projet n'aurait pas été possible sans Babel. Merci également à James (@thejameskyle) et Juriy (@kangax) pour leur aide jusqu'à la publication ! Nous tenons aussi à saluer Boopathi (@boopathi) que nous avons invité à nous épauler après avoir découvert son propre projet babel-minify !