JavaScript Modularization Summary

The modularization path of JavaScript could not be more zigzag.

In order to make the experience of writing JavaScript easier in the front-end development environment. There come several different JavaScript modularization standards.

From my personal experience of development using JavaScript, I have tried the raw method, sea.js method, require.js method and webpack method (miscellaneous method including node.js style, es6 style and others)

Raw Method

One example of the raw method practices is as following.

<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
  var jqxhr = $.ajax(the_api_url)
    .done(function(data) {
      console.log('success');
    })
    .fail(function(data) {
      console.log('fail');
    })
    .always(function() {
      alert('complete');
    });
</script>

As above, the first <script> tag injects jQuery module which defines jQuery and $ variables as objects(and of course also functions).

And based on the raw method, there come also many derivatives, such as enclosure.

(function (mod, $, _) {
    mod.add = ***;
    mod.sub = ***;
}((window.module_name = window.module_name || {}), jQuery, Underscore)); // jQuery and Underscore should be imported before this module definition.

And more advance usage including the usage of call() and apply() which would not be covered here.

CMD - Common Module Definition Method

Personally, I also call it sea.js method. There are something among CMD, commonjs and node.js, which would not be covered here.

One sea.js demo is as following.

// bar.js
define(function(require, exports, module) {
  // one possible implementation
  var $ = require('jquery');
  var object = {ajax: $.ajax};

  module.exports = object; 
});
// foo.js
define(function(require) {
  var bar = require('./bar');
  bar.ajax('/api').done(function(data){console.log('ajax done');});
});
// index.html, sea.js

<script src="../sea-modules/seajs/seajs/2.1.1/sea.js"></script>
<script>
  seajs.config({
    base: "../sea-modules/",
    alias: {
      "jquery": "jquery/jquery/1.10.1/jquery.js"
    }
  }); // sea.js configuration

  seajs.use("./foo");
</script>

More information about the usage of sea.js can be found under Sea.js - 5 minutes to get started and examples can be found under seajs/examples

AMD - Asynchronous Module Definition Method

Again, personally, I also call it require.js method. More information can be found under AMD.

define(id?, dependencies?, factory);
// foo.js
define(['jquery'], function ($) 
    function myFunc(){};

    return myFunc; // exposed public methods
}); // depends on 'jquery' module
// bar.js
define(['jquery', 'underscore'], function ($, _) {
    function a(){}; // private, because not returned
    function b(){}; // public, because returned
    function c(){}; // public, because returned

    return {
        b: b,
        c: c
    } // exposed public methods
}); // depends on 'jquery' and 'underscore' module

A very basic reference about require.js could be found under RequireJS basic introduction. And more information about require.js practices can be found under HOW TO GET STARTED WITH REQUIREJS.

[TODO: Add My rhophotos demo.]

CommonJS Method

CommonJS style is in fact not used in the front-end, but with the help of tools like Browserify and WebPack, front-end developers can also write in the commonJS style.

// index.js
var foo = require('./foo.js'); // relative paths 

foo.ajax('/api').done(function(data){console.log('ajax done');});
// foo.js
var $ = require('jquery'); // `node_modules/` paths

var object = {ajax: $.ajax}
module.exports = object;

Tool compilation

browserify index.js > bundle.js

And front-end usage

<script src="bundle.js"></script>

UMD - Universal Module Definition Method

This is a AMD and CommonJS compatible method. However, a little bit ugly as following demo shows.

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory); // AMD
    } else if (typeof exports === 'object') {
        module.exports = factory(require('jquery')); // CommonJS
    } else {
        root.moduleName = factory(root.jQuery); // Browser globals (root is window)
    }
}(this, function ($) {
    function myFunc(){}; // methods

    return myFunc; // exposed public method
}));

ES6

Since ES6 is still not fully supported by browsers before today (2018-04-27). Tools like WebPack is still required.

The export statement is used when creating JavaScript modules to export functions, objects, or primitive values from the module so they can be used by other programs with the import statement.

There are two different types of export, named and default. You can have multiple named exports per module but only one default export.

export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName(){...}
export class ClassName {...}

export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };

export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;
import defaultExport from "module-name"; // Importing defaults
import * as name from "module-name"; // Import an entire module's contents
import { export } from "module-name"; // Import a single export from a module
import { export as alias } from "module-name"; // Import an export with a more convenient alias
import { export1 , export2 } from "module-name"; // Import multiple exports from module
import { export1 , export2 as alias2 , [...] } from "module-name"; // Rename multiple exports during import
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name"; // Importing defaults and namespace imports 
import "module-name"; // Import a module for its side effects only

One demo is as following.

// foo.js
function getJSON(url, callback) {
  let xhr = new XMLHttpRequest();
  xhr.onload = function () { 
    callback(this.responseText) 
  };
  xhr.open('GET', url, true);
  xhr.send();
}

export default function getUsefulContents(url, callback) {
  getJSON(url, data => callback(JSON.parse(data)));
}
// index.js
import { getJSON } from './foo';

getJSON('http://www.example.com', data => { doSomethingUseful(data); });

More

Something I have just heard of but never tried by myself.

References


* cached version, generated at 2018-12-02 19:58:53 UTC.

Subscribe by RSS