
## <a href="#modules" name="modules">EcmaScript 6 Modules And Module Support</a>

Note: This content is subject to change and may be removed prior to launch.

Yeoman comes with experimental support for ES6 modules, made possible through Require HM. HM allows us to write ES.next module syntax and as long as code is saved in files with `.hm` extension, they can be used with RequireJS and AMD as if they were regular ES3/5 scripts.


*Note: The ES.next module specification is not yet complete and is subject to change. As such, the material below should be considered correct as of June, 2012 but for later dates the Harmony wiki entry on modules should be consulted to ensure correctness.

Also note that as Require HM is a RequireJS plugin, ES6 modules are only supported when used with RequireJS. We hope to change this in the future once support for ES6 modules in Google Traceur has improved.*

###module:

In ES6, A module is a unit of code contained within a `module` declaration. It can either be defined inline or within an externally loaded module file. A skeleton inline module for a Car could be written:

{% highlight javascript %}
module Car{
  // import …
  // export …
}
{% endhighlight %}
When we say *externally loaded modules*, we are referring to modules which are either loaded using `import` declarations or the Module Loader API. Both will be covered shortly.

A module *instance* is a module which has been evaluated, is linked to other modules or has lexically encapsulated data. Examples of modules instances are:

{% highlight javascript %}
module myCar = Car;
module myCar at "car.js";
{% endhighlight %}

`module` declarations can be used in the following contexts:

{% highlight javascript %}
module Universe {}
module Universe { module MilkyWay {} }
module MilkyWay = "Universe/MilkyWay"
module System = Universe.MilkyWay.SolarSystem
module System = SolarSystem

{% endhighlight %}

###export:

An export declaration declares that a local function or variable binding is visible externally to other modules. If familiar with the module pattern, think of this concept as being parallel to the idea of exposing functionality publicly.

{% highlight javascript %}
module Car{

  // Internals
  var licensePlateNo = "556-343"

  // Exports
  export function drive(speed, direction){
    console.log('We are driving at a speed of ' + speed + ', ' + direction);
  }

  export var miles = 5000;
  export var color = "silver";
}

{% endhighlight %}

Modules `import` what they wish to use from other modules. Other modules may read the module exports (e.g `drive()`, `miles` etc. above) but they cannot modify them. Exports can be renamed as well so their names are different from local names.

A module may also export other modules for consumption.

{% highlight javascript %}
module Car{
  export module engine{}
  export module driver{}
  export module seats{}
}
{% endhighlight %}

`export` can be used in the following contexts:

{% highlight javascript %}
export var document
export var document = { }
export function parse() { }
export module System = SolarSystem
export SolarSystem
export Mercury, Venus, Earth
export * from SolarSystem
export { Mercury: SolarSystem.Mercury, Earth: SolarSystem.Earth }
{% endhighlight %}


###import:

An import declaration binds another modules exports as local variables. Variables that are imported can be locally renamed to avoid naming conflicts.

{% highlight javascript %}
module Car{
  export function drive(speed, direction){
    console.log('details:', speed, direction);
  }

  export module engine{
    export function check(){ ... }
  }

  export var miles = 5000;
  export var color = "silver";

};
{% endhighlight %}

Revisiting the export example above, we can now selectively choose what we wish to `import` when in another module.

We can just import `drive()`:

{% highlight javascript %}
import drive from Car;
{% endhighlight %}

We can import `drive()` and `miles`:

{% highlight javascript %}
import {drive, miles} from Car;
{% endhighlight %}

We can import `check()` from our engine module:

{% highlight javascript %}
import check from Car.engine;
{% endhighlight %}

We can import all of the exports:

{% highlight javascript %}
import * from Car;
{% endhighlight %}

We can also import an entire file as a module:

{% highlight javascript %}
import "car.js" as Car;
{% endhighlight %}

Or import `drive()` without needing to bind the module to a local name:

{% highlight javascript %}
import drive from "car.js";
{% endhighlight %}

This similarly works with JavaScript libraries like Underscore.js:

{% highlight javascript %}
import reduce from "Underscore.js"
{% endhighlight %}


### module, import and export

Bringing these three concepts together:


{% highlight javascript %}
module vehicle{
  export function drive(speed, direction){
    console.log('We are driving at a speed of ' + speed + ', ' + direction);
  };

  export function stop(){
    console.log('We have stopped');
  };

  export var miles = 0;
  export var color = "silver";
  export var wheels = 4;
}

module basicExtras{
  export var carSeat = true;
  export var specialRims =  true;
  export var mp3Player = true;
}

module premiumExtras{
  export module GPS{
    //...
  }
}

{% endhighlight %}

{% highlight javascript %}
// Engine.js
module engine{

}
{% endhighlight %}

{% highlight javascript %}
module Car{
  import * from vehicle;
  import {specialRims, mp3Player} from basicExtras;
  import "engine.js" as engine;
  module navigationSystem from premiumExtras.GPS;

  export drive;
  export stop;
}
{% endhighlight %}

-- how do you rename exports?



### dynamically loading modules

Earlier, we mentioned the concept of a Module Loader API. The module loader allows us to dynamically load in scripts for consumption. Similar to `import`, we are able to consume anything defined as an `export` from such modules.

{% highlight javascript %}
// Signature: load( moduleURL, callback, errorCallback )

Loader.load("car.js", function(car) {
        console.log(car.drive(500, "north"));
    }, function(err){
        console.log("Error:" + err);
    });

{% endhighlight %}

`load()` accepts three arguments:

* moduleURL: The string representing a module URL (e.g "car.js")
* callback: A callback function which receives the output result of attempting to load, compile and then execute the module
* errorCallback: A callback triggered if an error occurs during loading or compilation

Whilst the above example seems fairly trivial to use, the Loader API is there to provide a way to load modules in controlled contexts and actually supports a number of different configuration options. `Loader` itself is a system provided instance of the API, but it's possible to create custom loaders using the `Loader` constructor.


{% highlight javascript %}
// The Loader constructor creates a new loader
var customLoader = new Loader(
    // Define the parent of this loader
    // if a custom one exists, otherwise
    // just use the default system Loader
    Loader, {

    // Global object for the Loader
    global: Object.create(null),

    // Loader's base URL
    baseURL: baseURL,

    // A flag indicating whether code should be evaluated
    // in strict mode
    strict: false,

    // Source of the loader intrinsics which can either
    // be an existing loader or just null
    linkedTo: Loader || null,

    // The module resolution hook
    resolve: function( relativeURL, baseURL ){..},

    // The module loading hook
    fetch: function( relativeURL, baseURL, request, resolved ){…},

    // A hook for source translation
    translate: function( src, relativeURL, baseURL, resolved ){…}
});
{% endhighlight %}


Let's review the final three hooks in more detail:

**fetch: function( relativeURL, baseURL, request, resolved ):**

Once a module is resolved, it must be fetched. The `fetch` hook allows us to fetch code from an external resource and returns its source via the first callback or rejecting the code via the second callback.


The `fetch` request object has three callbacks:

{% highlight javascript %}
request = {

  // callbacks for the loading hook

  // callback to create the successfully loaded source
  fulfill: function( src ){..},

  // callback to indicate the source should be loaded from a different URL
  redirect: function( url, baseURL ){..}

  // callback to indicate am error occurred in the loading
  reject: function( msg )
}
{% endhighlight %}

If we don't supply a `fetch` hook, the parent Loader's `fetch` is used instead.



**resolve: function( relativeURL, baseURL ):**



**translate: function( src, relativeURL, baseURL, resolved ):**

When code is evaluated, we have the option of translating the source of that code using this hook. The hook can either produce the final source code or throw an exception if something goes wrong.


A complete custom loader example could thus be written as follows:

{% highlight javascript %}
var customLoader = new Loader(Loader,{
    global: window,
    baseURL: document.URL.substring(0, document.URL.lastIndexOf('\/') + 1),
    strict: false,
    resolve: function (relURL, baseURL) {
      var url = baseURL + relURL;
      return url;
    },
    fetch: function (relURL, baseURL, request, resolved) {
      var url = baseURL + relURL;
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            request.fulfill(xhr.responseText);
          } else {
            request.reject(xhr.statusText);
          }
        }
      };
      xhr.open("GET", url, true);
      xhr.send(null);
    },
    translate: function (src, relURL, baseURL, resolved) {
      return src;
    }
  });
{% endhighlight %}


*Note: As Require HM is able to work with the RequireJS `define()` and `require()` syntax, it doesn't currently support the Module Loader API. If one is however required, there is a shim available for this feature [here](https://github.com/addyosmani/es6-module-loader/).*


### What else can be done with modules?

We can also define modules with a shared state:

{% highlight javascript %}
module Car{
  export module milesCounter {
      var miles = 0;
      export function addMile() { return miles++ }
      export function currentMiles() { return miles }
  };
};
{% endhighlight %}

or cyclic dependencies:

{% highlight javascript %}
module Car {
    import * from Scooter;
    export function even(n) {
        return n == 0 || odd(n - 1);
    }
}

module Scooter {
    import * from Car;
    export function odd(n) {
        return n != 0 && even(n - 1);
    }
}
{% endhighlight %}


*Note: Require HM does not presently support cyclic dependencies. We are working on fixing this limitation.*




