The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or clickhereto continue anyway

Babili (babel-minify) Babel twitter

Posted Aug 30, 2016 by Henry Zhu

We released Babili as beta (0.0.1) a few days ago under an MIT license!

Try it out in the Babel REPL and report any bugs or potential optimizations we can make! Theres also a #minify slack room!

There are a lot of (valid) questions about why a new minifier is a good idea, so this post should help with that.

TL;DR: Babili can accept ES2015+ input, while current minifiers are mostly limited to ES5, requiring code to be transpiled before minification. This is becoming unncessary as people begin to ship ES2015 to clients. Babili is also modular/flexible (being a Babel preset means it supports user plugins) and can be used as a preset or CLI tool. Babili will also be able to make ES2015+ specific optimizations.

Pronunciation

# sounds like "bah billy" or "Babadi" (from DBZ)
say Babili

Babili is Babylon in Akkadian.

If you cant remember the name, babel-minify works too (made an issue for the name).

Why minify?

At a basic level, minification removes unnecessary characters from a program without changing its functionality things like comments, whitespace, newlines, and extra parentheses. Advanced minification may transform programs into smaller equivalents and remove redundant/unreachable code.

Minification is primarily useful for decreasing the size of the JavaScript payload sent from the server to the client: users will download less code to use your website. Advanced minification can also result in shorter parse time (less code to parse) and in some cases faster runtime (e.g. advanced optimizations like function inlining).

Current minifiers

Tools such as Uglify dont currently support targeting the latest version of ECMAScript (not yet: harmony branch).

We currently use tools like Babel to compile ES2015 code down to ES5 code to support older browsers. Then we use something like Uglify to cut down on the bundle size.

As browsers implement more ES2015 features and we drop support for older browser versions, there is a sliding window of the version of ECMAScript you write in and the target ECMAScript version you minify to. However since Uglify cannot parse ES2015+, you would still have to compile down to ES5 anyway.

Babili

Thats where Babili comes in.

Babili is ES2015+ aware because it is built using the Babel toolchain. It is written as a set of Babel plugins, consumable with the babili preset.

Example

Say were targeting the latest versions of Chrome, Firefox, Edge, and Safari all of which support ES2015 classes. Then, compiling ES2015 classes to a constructor function and prototype methods (ES5) results in more code (and potentially loses any optimizations browsers might have for classes).

class Mangler {
  constructor(program) {
    this.program = program;
  }
}
// need this since otherwise Mangler isn't used
new Mangler();

Before, we might run Babel to transpile the class into a function and run Uglify on the compiled code to send to the browser.

// ES2015 code -> Babel -> Uglify/Babili -> Minified ES5 Code
var a=function a(b){_classCallCheck(this,a),this.program=b};a();

With Babili, you can just run the minifier which works on ES2015 code.

// ES2015 code -> Babili -> Minified ES2015 Code
class a{constructor(b){this.program=b}}new a;

Also its important to note that this isnt specific to ES2015. Because Babel updates as ECMAScript updates (with ES2015, ES2016, and now ES2017) and follows the proposal process for experimental features (with our stage-x presets), the minifier should be able to output whatever version of ECMAScript that is supported.

In the future, we might make use of the ES2015+ syntax information we have at compile time (e.g. we know that given function is an arrow function or that a given binding is block-scoped etc) to do advanced optimizations. And we can make use of the knowledge that were targeting an ES2015+ environment in creative ways.

Were just getting started so let us know if you have any ideas!

To give an idea of some of the transforms:

babel-plugin-minify-constant-folding:

Tries to evaluate expressions and inline the result. For now only deals with numbers and strings.

2 * 3;
"b" + a + "c" + "d" + g + z + "f" + "h" + "z"
6;
"b" + a + "cd" + g + z + "fhz";

babel-plugin-minify-mangle-names:

Context- and scope- aware variable renaming.

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);
  }
}

Usage

Babel Preset

If you already use Babel, you can just add the babili preset (babel-preset-babili) to your config.

You will want to enable this only in production, so use the env option which uses either process.env.BABEL_ENV or process.env.NODE_ENV

$ npm install babel-preset-babili --save-dev
// previous .babelrc
{ "presets": ["es2015"] }
// .babelrc
{
  "presets": ["es2015"],
  "env": {
    "production": {
      "presets": ["babili"]
    }
  }
}

One issue with using Babili as a preset is that then Babili would only run per-file rather than on the whole bundle. Minification usually happens after bundling as with the UglifyJsPlugin in webpack. However, running it after bundling would lose the speed benefits (needs to be measured) of doing the transpiling/minification in the same step. Again, this is something we need to think about: how to intergrate or pass more information to the bundler.

Babili CLI

If you dont use Babel, you can use our standalone CLI tool babili. (Currently its just a wrapper for babel-cli + the preset). You could run this after transpiling (or not) in place of Uglify.

$ npm install babili --save-dev
$ babili src -d lib
# equivalent to
# babel src -d lib --presets=babili --no-babelrc

Webpack

You can just use the preset with babel-loader.

$ npm install babel-core babel-loader babel-preset-babili
module: {
  loaders: [
    {
      test: /\.js$/,
      loader: 'babel',
      query: {
        presets: ['babili']
      }
    }
  ]
}

Or use it seperately with the babili-webpack-plugin (made by @boopathi, who also works on 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)
  ]
}

We want to have a better story with integration with Webpack/bundlers in the near future! Also check out #100.

Pros/Cons

Uglify Pros

Uglify Cons

Babili Pros:

Babili Cons:

TL;DR: Babili should be able to keep up with the ECMAScript standard as new features get added as well as target the environments you need to support. It has a lot of potential: it may not be as production-ready as Uglify at the moment since it was just released but as we continue to optimize with more users it should be more than capable.

How to Help

Amjad had been working on this project for a while but we decided to release it earlier as a beta to allow the community to test it out and both contribute through reporting bugs and patches.

Its still early days for this project so theres a lot to help out with! Our next priority is to make Babili more stable/robust for a 1.0.0 release.

We will be working to get it as fast and produce code sizes as small as Uglify/Closure Compiler in simple mode.

Huge thanks to Amjad (@amasad) for starting this project and Facebook for allowing us to release this under the Babel organization as an MIT licensed project! Sebastian (@kittens) was obviously a big part of this given this wouldnt have been possible without Babel. Also thanks to James (@thejameskyle), Juriy (@kangax) for helping see this through to release! Also want to give a shoutout to Boopathi (@boopathi) who we invited to help us out after seeing the work on his own babel-minify project!

Continue reading on babeljs.io