June 22, 2015

GSoC: Week 4 - Adding AMD and ECMAScript 2015 support

I have been accepted to this years Google's Summer of Code to work on ClojureScript. The goal of my project is to improve the integration of ClojureScript with the existing JavaScript ecosystem. I will post weekly updates about the progress of the project here. For more details about the project have a look at the ClojureScript GitHub wiki page.

Last week, we made further progress in adding JavaScript module support to ClojureScript. David merged two patches, one for AMD module support and the other for ECMAScript 2015 module support. In this post, I will describe how to use AMD and ECMAScript 2015 modules in a ClojureScript project.

AMD

Adding support for AMD is very similar to adding support for CommonJS. The only difference is that we first rewrite an AMD module to a CommonJS module before converting it to a Google Closure module. Both can be done with the Google Closure compiler. Currently, the Google Closure compiler supports the following AMD define signatures:

define(function() ...)
define(OBJECT_LITERAL)
define(['dep', 'dep1'], function(d0, d2, [exports, module]) ...)

For example, the following is an AMD module that can be processed by the Google Closure compiler:

// greeting.js
define(function () {
    return {
        hello: function (name) {
            return "Hello, " + name;
        }
    };
});

To be able to include this module, we need to build our own version of the Google Closure compiler and the ClojureScript compiler. The reason for this is that we are using the package private class TransformAMDToCJModules from the Google Closure compiler to rewrite an AMD module to a CommonJS module. We need to make the class and its constructor public to be able to use this functionality. We have already submitted a patch for this and the change will hopefully be merged and included in the next release of the Google Closure compiler. But for now, clone the Google Closure compiler repository, build it and install it to your local maven repository as follows:

$ git clone git@github.com:google/closure-compiler.git
$ cd closure-compiler
$ ant jar
$ mvn install:install-file -Dfile=build/compiler.jar -DgroupId=com.google.javascript -DartifactId=closure-compiler -Dversion=v20150622-SNAPSHOT -Dpackaging=jar

Before building a new version of the ClojureScript compiler (see the previous post) change the version of the Google Closure compiler in ClojureScript's project.clj file to the same version you used to install the Google Closure compiler JAR to your local maven repository, for example:

[com.google.javascript/closure-compiler "v20150622-SNAPSHOT"]

Finally, include the AMD module with the new compiler option module-type and the value :amd:

:foreign-libs [{:file "libs/greeting.js"
                :provides ["greeting"]
                :module-type :amd}]

ECMAScript 2015

The Google Closure compiler includes the functionality to transpile from ECMAScript 2015 to a lower version. We are using this functionality to add support for ECMAScript 2015 modules and are converting ECMAScript 2015 modules to Google Closure ECMAScript 5 modules.

// greeting.js
export function hello(name) {
    return "Hello, " + name;
};

To include the above module, we need to build a recent version of the ClojureScript compiler (see the previous post) and use the new compiler option module-type with the value :es6:

:foreign-libs [{:file "libs/greeting.js"
                :provides ["greeting"]
                :module-type :es6}]
Tags: cljs ecmascript 2015 js modules amd gsoc