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.
- KMD, kill amd and cmd
- YUI, Yahoo! UI
References
* cached version, generated at 2018-12-02 19:58:53 UTC.
Subscribe by RSS