Modular JavaScript – An introduction to RequireJS & Browserify – The dark past



Modular JavaScript – An introduction to RequireJS & Browserify – The dark past

0 0


Modular-JavaScript-Talk

Slides for my HannoverJS-talk about modular JavaScript, RequireJS and Browserify

On Github herschel666 / Modular-JavaScript-Talk

Modular JavaScript

An introduction to RequireJS & Browserify

ToC

Who's talking? The dark past CommonJS & AMD? What is this?? RequireJS Browserify UMD What's next?

Who's talking?

Emanuel Kluge

The dark past

Pollution of the global namespace

                            var some_value = 'foo';

function do_some_stuff() {
    // …
}

function do_some_other_stuff() {
    // …
}
                        

Module pattern to the rescue

                            var APP = {} || APP;

var APP = (function (APP) {
    APP.someMethod = function () {…}
    return APP;
})(APP);

var APP = (function (APP) {
    APP.someOtherMethod = function () {…}
    return APP;
})(APP);
...
                        

Spaghetti code vs. <script>-armada

Writing everything in a single file is a no-go!

Including each file with a <script>-tag while keeping the correct order is tedious work to do.

No proper Dependency Management

A bunch of <script>-tags, serially processed, is insufficient.

CommonJS & AMD? What is this??

CommonJS

  • An informal group of JS afficionados founded by Kevin Dangoor in January 2009
  • The goal is to design reasonable APIs for common application needs
  • Document those designs
  • Implement those designs - on servers, in browsers, in command-line apps & in desktop apps

Modules/1.1

  • The CommonJS Module specification for client- and server-side-use
  • Implemented by Node.js, Narwhal, etc.
  • Doesn't fit browser's needs due to their asynchronous nature

CommonJS example

var moduleA = require('modules/module-a');

module.exports.foo = function (bar) {
    return moduleA.doStuff(bar);
};

AMD

The Asynchronous Module Definition brings the module system to the browser environment.

AMD example

define(['modules/deps-a', 'modules/deps-b'], function (depsA, depsB) {

    var foo = depsA.someMethod();

    return {
        doBar: function (foo) {
            return depsB.create(foo);
        }
    };

});
require(['main'], function (foo) {
    foo.doBar('foobar');
});

So how do I get JS modules to work in my browser?

RequireJS

Made by James Burke (@jrburke)

A popular and mature implementation of the AMD-specification

Examples

The AMD-syntax

define(['some-module'], function (someModule) {
    return {
        foo: function (bar) {
            return someModule.doStuff(bar);
        }
    };
});

The CommonJS-like syntax *

define(function (require, exports, module) {

    var someModule = require('some-module');

    exports.foo = function (bar) {
        return someModule.doStuff(bar);
    };

});

*: Does only work in browsers that support Function.prototype.toString

I don't like AMD! And wrapped CommonJS-syntax sucks balls!!

Browserify FTW

  • Made by James Halliday (@substack)
  • Enables the use of CommonJS-/Node-modules in the browser; compiles a single script file out of the modules.
  • Provides browser versions of Node's core-libraries like events, path, http, ….

Browserify example

var util = require('util'),
    str = 'This script\'s path is %s';

module.exports = function () {
    return util.format(str, __filename);
};
  • Easy integration into Grunt-workflow with Grunt-browserify
  • Lots of transform plugins to e. g. consume AMD- or ES6-modules, Coffeescript, …. (List)

I'm releasing a library. Which specification should I target?

Use the UMD, Luke!

  • A module-wrapper that supports CommonJS, AMD and the good ol' global variable
  • Each possible environment gets its module, the global variable is actually optional but nice to have

The mighty UMD-chunk

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['exports', 'b'], factory); // AMD
    } else if (typeof exports === 'object') {
        factory(exports, require('b')); // CommonJS
    } else {
        factory((root.commonJsStrict = {}), root.b); // Browser globals
    }
}(this, function (exports, b) {
    exports.action = function () {
        // do stuff …
    };
}));

What's next? o.O

EcmaScript6 “Harmony”

Modules finally arrive in JavaScript.

import 'modules/some-module' as someModule;

export function foo(bar) {
    return someModule.doStuff(bar);
};

Just one way of importing and exporting.

A decent Loader is there as well.

System.import(
    ['modules/some-module'],
    function (someModule) {
        // do fancy stuff with `someModule`
    },
    function (err) {
        // something went wrong
    }
);

AMD-style syntax module-loading.

System.load(
    ['vendor/jake-weary.js'],
    function (dollarz) {
        // do crazy stuff
    },
    function (err) {
        // no jake …
    }
);

Same syntax but different method for loading common JS-files.

The Loader API

  • Provides various hooks to customize the loading procedure
  • Enables Linting on-the-fly and automatic code translation (CoffeeScript, Typescript)
  • Weapon of choice to deal with legacy modules (CommonJS Modules/1.1, AMD)

Thank you!

Go ye and write modular JavaScript.

More infos!