Skip to content

Comparisons with other tools

Chris Rebert edited this page May 7, 2015 · 4 revisions

Work in progress! Proper comparisons coming soon - some of this stuff may be out of date.

The summary: Esperanto is much faster than similar tools (it uses string manipulation tricks, rather than full-blown AST transformation), ridiculously easy to use, doesn't muck about with your formatting, and doesn't complain that it can't find your external dependencies. It doesn't care at all about the rest of your architecture - no need to use a specific module loader.

There are already a couple of ES6 module transpilers and loaders. Let's consider this simple example...

import foo from 'foo';
var bar = foo.toUpperCase();
export default bar;

...and see how they fare.

var transpile = require( 'transpile' );

var transpiled = transpile.to({
  name: 'test',
  source: test, // the contents of the module
  metadata: { format: 'es6' }
}, 'amd' );

Pretty easy - we just tell it what input and output formats to use, and off it goes. It's a bit of a shame that you have to specify a name property, since AMD best practice is to use anonymous modules, but never mind. What does the result look like?

define('sample', ['foo'], function ($__0) {
  'use strict';
  if (!$__0 || !$__0.__esModule)
    $__0 = { 'default': $__0 };
  var foo = $traceurRuntime.assertObject($__0).default;
  var bar = foo.toUpperCase();
  var $__default = bar;
  return {
    get default() {
      return $__default;
    },
    __esModule: true
  };
});

Wait, I'm supposed to use Traceur in production? No thanks! Oh, and I still need to support IE8, so that get default() is a no-go.

var transpiler = require( 'es6-module-transpiler' );
var Container = transpiler.Container;
var FileResolver = transpiler.FileResolver;
var BundleFormatter = transpiler.formatters.bundle;
var AmdFormatter = require( 'es6-module-transpiler-amd-formatter' );

var container = new Container({
  resolvers: [new FileResolver(['./'])],
  formatter: new AmdFormatter()
});

container.getModule('test');
container.write('output/test.js');

This time, rather than passing in a string, we have to point the transpiler to the files on disk. That's because it actually follows the dependency graph of your modules, so that it can (if you're not using the AMD formatter) bundle up your source code into a single file. If it can't find a module, it errors out - so as far as I can tell, it's impossible to use es6-module-transpiler if you have external dependencies (e.g. in a bower_components folder) that aren't packaged as ES6 modules.

Leaving that aside, what does the result look like?

define("test", ["foo", "exports"], function(foo$$, __exports__) {
  "use strict";

  function __es6_export__(name, value) {
    __exports__[name] = value;
  }

  var foo;
  foo = foo$$["default"];
  var bar = foo.toUpperCase();
  __es6_export__("default", bar);
});

//# sourceMappingURL=es6-module-transpiler.js.map

Better, certainly, and you get source maps which is really cool. Though as with transpile, you're stuck with named (as opposed to anonymous) AMD modules. Frankly, though, the external dependencies thing is a dealbreaker for me.

Here's the code to generate AMD output:

var transpiled = esperanto.toAmd( test );

And here's the output:

define(['foo'],function (foo) {

  'use strict';

  var bar = foo.toUpperCase();
  return bar;

});

No muss, no fuss. Oh, and did I mention that it's an order of magnitude faster than the alternatives? See here for more comparisons.