Using AMD loaders to write and manage modular javascript

Boston JavaScript, 2011-04-11

John Hann, UI Architect. lifeIMAGE, Inc.

@unscriptable


huh?

"I thought you were going to talk about RequireJS?"


I will!

RequireJS started the
AMD revolution!

*ducks*


What is AMD?


Asynchronous
Module
Definition


Asynchronous
Module
Definition

why?


Asynchronous
Module
Definition


Asynchronous
Module
Definition

why?


Asynchronous
Module
Definition


Asynchronous
Module
Definition

why?


Asynchronous
Module
Definition


What is CommonJS?


Why AMD?


Why AMD?

freedom of choice

(more "in the works")


Why AMD?

plugins! AMD is not just for js modules


Why AMD?

momentum


Why AMD?

interoperability

node.js, narwhal, CommonJS Modules

(require wrapping / conversion)


How does AMD work?

define() is the key to interop


define(*)

* this is a gated community


define()
The Gated Community


define()

typical module

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        var myModule = {};
        // build your module here
        myModule.foo = depA.getFoo();
        return myModule;
    }
);
    

define()

module wrapper

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        var myModule = {};
        // build your module here
        myModule.foo = depA.getFoo();
        return myModule;
    }
);
    

define()

dependency list

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        var myModule = {};
        // build your module here
        myModule.foo = depA.getFoo();
        return myModule;
    }
);
    

define()

definition function

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        var myModule = {};
        // build your module here
        myModule.foo = depA.getFoo();
        return myModule;
    }
);
    

define()

this one defines an object (module)

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        var myModule = {};
        // build your module here
        myModule.foo = depA.getFoo();
        return myModule;
    }
);
    

define()

can also define a constructor (shown) or a function

define(
    [
        'depA',
        'depB',
        'depC'
    ],
    function (depA, depB, depC) {
        function myConstructor {};
        myConstructor.prototype = {
            // specify methods and properties
        };
        return myConstructor;
    }
);
    

define()

simple module with no dependencies

define({
    theAnswer: 42,
    doubleIt: function (x) {
        return 2 * x;
    }
});
    

define()

wrapper for a CommonJS module

define(

    /***** no deps *****/

    function (require, exports, module) {
        if (/^https:\/\//.test(module.uri)) {
            exports.isSecureTransport = true;
        }
        else {
            exports.isSecureTransport = false;
        }
        // also: this === exports
    }
);
    

define()

nested require(). note relative path!

define(
    [
        'require',
        'depA',
    ],
    function (req, depA) {
        if (!(depA.optionalResource)) {
            req(['./optionalResource'], function (opt) {
                depA.optionalResource = opt;
                depA.callback();
            });
        }
        else {
            depA.callback();
        }
    }
);
    

require(*)

* this is NOT a gated community


require(!)

! this is The Wild West


require()
The Wild West


require()
The Wild West

simple example of require()

require(
    ["modA", "modB"],
    function (modA, modB) {
        // do something with modA and modB
        // when they are fully loaded
    }
);
    

require()
The Wild West

public API

require(
    ["modA", "modB"],
    function (modA, modB) {
        // do something with modA and modB
        // when they are fully loaded
    }
);
    

require()
The Wild West

dependency list

require(
    ["modA", "modB"],
    function (modA, modB) {
        // do something with modA and modB
        // when they are fully loaded
    }
);
    

require()
The Wild West

callback function

require(
    ["modA", "modB"],
    function (modA, modB) {
        // do something with modA and modB
        // when they are fully loaded
    }
);
    

require()
The Wild West

domReady and RequireJS

require(
    [
        "modA", 
        "modB"
    ],
    function (modA, modB) {
        require.ready(function () {
            // do something with the dom, 
            // modA, and modB
        });
    }
);
    

require()
The Wild West

domReady and curl.js

require(
    [
        "modA",
        "modB",
        "curl/domReady"
    ],
    function (modA, modB) {
            // do something with the dom, 
            // modA, and modB
    }
);
    

require() is actually an alias for curl()


require()
The Wild West

non-AMD Javascript and RequireJS

require(
    [
        "order!modA.js",
        "order!modB.js"
    ],
    function (modA, modB) {
        // do something with modA and modB
        // modB needs modA to be loaded first
    }
);
    

require()
The Wild West

non-AMD Javascript and curl.js

require(
    [
        "js!modA!order",
        "js!modB!order"
    ],
    function (modA, modB) {
        // do something with modA and modB
        // modB needs modA to be loaded first
    }
);
    

require()
The Wild West

curl.js's chaining API

curl([
    'curl/domReady',
    'js!my/lib.js'
]).next([
    "js!modA!order",
    "js!modB!order"
]).then(
    function (modA, modB) {
        // do something
    },
    function (ex) {
        // show the loading error
    }
);
    

Show me the codez plz!


John Hann, UI Architect

lifeIMAGE, Inc.

unscriptable.com
@unscriptable