Modules

Saying 'module' we can mean:

  • The Module pattern
  • Object literal notation
  • AMD modules
  • CommonJS modules
  • ES6 modules

Object literal

var myModule = {
  myProperty: "someValue",
  myConfig: {
    useCaching: true
  },
  myMethod: function ( config ) {
    /* ... */
  }
}

Module

var myModule = (function (){
  var myPrivateData = "HAXXORSWON'TGETMYSECRET"
  return {
    publicMethod: function doSomeStuff(arg) {
      /* use myPrivateData here */
    }
  }
})();

myModule.publicMethod('ok');

Namespace

var myApp = myApp || {};
myApp.myModule = ...

Script loading

AMD

Asynchronous Module Definition

Solution for modular JavaScript that developers can use today (or yesterday). It was born out of Dojo's real world experience using XHR+eval and proponents of this format wanted to avoid any future solutions suffering from the weaknesses of those in the past.

Two words:

REQUIRE

DEFINE

define(
    module_id /*optional*/,
    [dependencies] /*optional*/,
    definition function /*function for instantiating the module or object*/
);
require([
  module_id, /* optional */
  module_id2, /* optional */
  module_id3, /* optional */
])

Anonymous

Anonymous modules

path ~ module_id

Config

require.config({
  baseUrl: '/another/path',
  paths: {
    'lodash': 'bower_components/lodash/dist/lodash.js'
  }
})
require(['lodash'], function (_) { /* ... */ })

Plugins

Why?

  • Clear proposal for defining flexible modules.
  • Significantly cleaner than the present global namespace and <script> tags.
  • Module definitions are encapsulated, avoiding pollution of the global namespace.
  • Most AMD loaders support loading modules in the browser without a build process.
  • Provides a "transport" approach for including multiple modules in a single file.
  • It's possible to lazy load scripts if this is needed.

Almond.js

R.js

Example build.js

CommonJS-like style

define(function(require) {
  var $ = require('jquery'),
      _ = require('lodash'),
      model = require('./model');
});

Browser & server-side

In-browser

CommonJS

Sample

var lib = require('lib');
var localLib = require('./local-lib');

function lol(){
   return localLib.modifyLol(lib.lol())
}
module.exports = lol

Run the demo

console.log(module, typeof module);
console.log(module.exports, typeof module.exports);

In-browser:

  • curl.js
  • PING

Server-side:

Browserify

by @substack

Browserify hat

UMD

// creating commonJsStrict module
(function ( root, factory ) {
    if ( typeof exports === 'object' ) {
        // CommonJS
        factory( exports, require('b') );
    } else if ( typeof define === 'function' && define.amd ) {
        // AMD. Register as an anonymous module.
        define( ['exports', 'b'], factory);
    } else {
        // Browser globals
        factory( (root.commonJsStrict = {}), root.b );
}(this, function ( exports, b ) {
    //use b in some fashion.
    // attach properties to the exports object to define
    // the exported module properties.
    exports.action = function () {};
}));

ES6 modules

Quick examples

// default export
export default jQuery;
// exports this class as "File"
export class File() { /* implementation */ }
// use shorthand objects to export 2 functions
export { encrypt, decrypt };
// import the default export of a module
import $ from "jquery";
// using 2 non-defaults exports
import { encrypt, decrypt } from "crypto";
// binding a module's exports to variables
import { unlink as rm } from "fs";
// binding and renaming one of a module's exports
import * as fs from "fs";
/* and say, use `fs.unlink` further on */

Get over here, module

// loading from external
import { y } from "foo";

import "foo";                // fetches "foo" at compile time

System.import("foo").then(function (fooModule) {
  let foo = fooModule;
}); // succeeds at runtime

Module Tag

<script type="module">
  // loads the 'q' export from 'mymodule.js' in the same path as the page
  import { MyConstructor } from 'mymodule';

  new MyConstructor();
</script>

Config

System.baseURL = '/another/path';
System.paths['lodash'] = 'bower_components/lodash/dist/lodash.js'
System.import('lodash').then(function(_) {
  /* ... */
})

Right here, right now.

Module reading you need.

Kottans