Evaluating traceur and babel in rails environment to see how well they behave in converting simple Ecmascript 6 file.

Our competitors today are

Notes:

  • traceur-rails works for some cases but fails for ”let” statement
  • sprockets-traceur seems to fare better than traceur-rails
  • sprockets-es6 is not production ready yet (depends from beta version of sprockets 4)

Original
[code lang=”javascript”]
import { Example } from ’test/example’;

class Test {
constructor() {
console.log(”test class instantiated”);
}

foo() {
return ”x”;
}
}
console.log(”loaded test module”);

new Test();
new Example();
[/code]

traceur-rails

Configuration:
[code lang=”ruby”]
Traceur::Config.compile_to = :register
[/code]

Result:
[code lang=”javascript”]
System.register(”test/test”, [], function() {
”use strict”;
var __moduleName = ”test/test”;
var Example = $traceurRuntime.assertObject(System.get(”test/example”)).Example;
var Test = function Test() {
console.log(”test class instantiated”);
};
($traceurRuntime.createClass)(Test, {foo: function() {
return ”x”;
}}, {});
console.log(”loaded test module”);
new Test();
new Example();
return {};
});
[/code]

sprockets-traceur

Configuration:
[code lang=”ruby”]
Traceur.configure do |c|
precompiled = !(Rails.env.development? || Rails.env.test?)
c.default_compilation_options.modules = :register
c.default_compilation_options.source_map = !precompiled
end
[/code]

Result:
[code lang=”javascript”]
System.registerModule(”test/test”, [], function() {
”use strict”;
var __moduleName = ”test/test”;
var Example = System.get(”test/example”).Example;
var Test = function Test() {
console.log(”test class instantiated”);
};
($traceurRuntime.createClass)(Test, {foo: function() {
return ”x”;
}}, {});
console.log(”loaded test module”);
new Test();
new Example();
return {};
});

//# sourceMappingURL=data:application/json;base64,eyJ2ZX…
;
[/code]
sprockets-es6
[code lang=”javascript”]
// NA – failed to get sprockets-es6 to work
[/code]

sprockets-es6 using online test in babel website
Babel online transform tester
[code lang=”javascript”]
”use strict”;

var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(”Cannot call a class as a function”); } };

var Example = require(”test/example”).Example;

var Test = (function () {
function Test() {
_classCallCheck(this, Test);

console.log(”test class instantiated”);
}

_createClass(Test, {
foo: {
value: function foo() {
return ”x”;
}
}
});

return Test;
})();

console.log(”loaded test module”);

new Test();
new Example();
[/code]

Notes

  • traceur-rails wants files to use .tc extension, which is a bit ackward
  • sprockets-traceur uses .js.es6 or .es6 file extension
  • sprockets-es6 uses .es6 file extension for files
  • sprockets-traceur generates embedded source maps by default into generated files. These source maps work well in development mode, in production they naturally won’t work, thus generation of them for production should be turned off
  • Regarding editors, Emacs with latest version of js2-mode combined with latest version of flycheck (with jshint) appears to be now in usable state. Just check and install latest versions of packages via ”M+x package-list-packages.
  • Caveat Emptor: Traceur requires that nodejs is installed, which causes slightly undesired extra dependency for assets precompile. Possible fix for this is to precompile assets locally and scp results to deployed server.

Conclusion
For a while, I would recommend sprockets-traceur, since it appears to be most robust from this set of competitors. Considering output format, not seeing real benefits into either direction, but I slightly prefer more compact output of traceur. However, traceur output format with ”:register” mode works neatly with rails javascript assets precompile. In the future if sprockets-es6 becomes standard part of sprockets gem, then I would start considering switching into it. However, it’s very likely thjat sprockets 4 will work only with very latest version of rails, which would hinder it very quickly as no-go option.