The new version of JavaScript, known as EcmaScript 6 or simply ES6, introduces the notion of modules and new syntax specific for them. This guide explores a combination of tools and conventions that help you author your code using these new primitives on top of the YUI infrastructure.
Modules in EcmaScript 6 are based on two main keywords: import
and export
.
This contrasts to YUI modules because in ES6 the export side is composed of a
series of exports instead of additions made to a common object, the Y
object.
Modules also introduce the concept of "default" exports as the main entry point
to a module.
export
is followed by one of:
export var foo = bar
.export function foo() {}
.as
. For example: export { foo as bar, baz }
.
A module without imports would look like this:
var initialCount = 2; var counter = initialCount; function count() { return counter++; } export var isCounting = true; export { initialCount as startValue }; export default count;
Importing works in a similar fashion. import
must be followed by one of:
import foo from 'my-module'
.as
. For example:
import { foo as bar, baz } from 'my-module'
.Both types of import declaration can be combined to import the default export of a module alongside other named exports by separating them with a comma:
import count from 'counter'; import { startValue as initValue, isCounting } from 'counter'; export function countPixels() { if (!isCounting) { throw new Error('Counter is not working'); } return count() + 'px'; };
Authoring code using the ES6 module syntax brings several new advantages and disadvantages:
Since YUI 3.15.0 supports loading ES6 modules transpiled to YUI modules that
look slightly different from traditional YUI modules. Instead of adding
properties to the Y
object, the return value of the module factory
function is stored as the module exports.
Here is the result of transpiling one of the previous examples:
YUI.add("pixel-counter", function(Y, NAME, __imports__, __exports__) { "use strict"; /*jslint esnext: true*/ var count = __imports__["counter"]["default"]; var initValue = __imports__["counter"].startValue; var isCounting = __imports__["counter"].isCounting; function countPixels() { if (!isCounting) { throw new Error('Counter is not working'); } return count() + 'px'; }; __exports__.countPixels = countPixels; return __exports__; }, "@VERSION@", {"es":true,"requires":["counter"]});
Imports are received inside an object as a parameter of the factory function. As a convenience, an object for storing the exports is also created, but the actual exports of the module are the ones in the value returned by the factory function.
The es6-module-transpiler
is
a Node
application that parses modules written using the ES6 module syntax and
compiles them to other JavaScript source files using Node's module system, AMD
modules or YUI modules.
You can install it with npm globally and use it as a command line tool called
compile-modules
$ npm install -g es6-module-transpiler $ compile-modules ./src-dir --to ./build-dir --type=yui
Since the ES6 syntax does not have a way to specify the name of the module, the transpiler must either receive the name beforehand or infer it from the file name. Both options are available from the command line:
$ compile-modules ./es6-mod.js --to ./build-dir --type=yui --module-name=foo $ compile-modules ./src-dir --to ./build-dir --type=yui --infer-name
Since these transpiled modules are not traditional YUI modules,
YUI().use()
would not work for loading them into a page. Instead,
use YUI().require()
which has a similar signature but also passes a
second argument to the callback that contains all the ES6 required modules.
YUI().require('pixel-counter', function (Y, __imports__) { var countPixels = __imports__['pixel-counter'].countPixels; // Use countPixels... });