https://github.com/umdjs/umd
https://github.com/systemjs/systemjs
https://www.linkedin.com/pulse/amd-vs-common-js-umd-damodaran-sathyakumar - done reading
https://auth0.com/blog/javascript-module-systems-showdown/ - done reading (03/15/2016)
https://addyosmani.com/writing-modular-js/
http://stackoverflow.com/questions/16521471/relation-between-commonjs-amd-and-requirejs
https://medium.com/@brianleroux/es6-modules-amd-and-commonjs-c1acefbe6fc0#.h8g11cs7l
https://dzone.com/articles/javascript-module-systems-showdown-commonjs-vs-amd
http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/
https://www.leanpanda.com/blog/2015/06/28/amd-requirejs-commonjs-browserify/
http://davidbcalhoun.com/2014/what-is-amd-commonjs-and-umd/
https://www.reddit.com/r/javascript/comments/3vqgai/eli5_commonjs_vs_amd_vs_es6/
http://tagneto.blogspot.com/2012/01/reply-to-tom-on-amd.html
http://unscriptable.com/2011/09/30/amd-versus-cjs-whats-the-best-format/
// JavaScript - AMD versus CommonJS:
AMD, Common JS are nothing but two styles of authoring Javascript code that help
in making the code modular. By saying modular, we mean to author code, such
that it:
1. is a well encapsulated unit that performs a certain functionality,
2. has well defined single responsibility,
3. has all its dependencies sorted out,
4. can be plugged into other modules
5. can be dynamically loaded / lazy loaded
AMD - (Asynchronous Module Definitions) made popular by Require JS, Curl JS is
very much suited to the browser. Common JS style, is something that is used in
the Node world.
That being said, it is possible to still author Common JS style modules for the
browser & use it via Browserify and also use a simplified Common JS wrapper over
the Require JS modules, to convert them into Common JS.
define('mathOps', ['jquery','underscore'], function ($, _) {
// methods
function sum(a,b) {
return a + b;
};
function multiply(a,b) {
return a * b;
}
function divide(a,b) {
return a / b;
}
function subtract(a,b) {
return a - b;
}
function updateResult() {
// use $ and _ to update something
}
// expose public methods
return {
sum: sum,
multiply: multiply,
division: division,
updateResult: updateResult
}
});
The above code is in AMD style. It encapsulates the functionality within a
define statement. It is a single responsibility module - performing math
operations. Its dependencies are listed upfront - jQuery & Underscore JS.
The callback within define doesn't execute until the dependencies are loaded /
resolved. This module is pluggable and can be plugged as a dependency inside
another module and re-used. The dependencies that are listed upfront - jQuery &
underscore are aliased in the callback functions as - $ and _, for use within
the module.
In the ideal case, dependencies are loaded asynchronously (via injected scripts
inside the <head> tag, so that they don' block the browser. Once the dependencies
are loaded, the callback fires and returns the object with its functions inside
the return statement.
But, in production apps, this doesn't work well and which is why require AMD
modules need to be built into one single file and rendered - via the Require.js
optimizer.
var $ = require('jquery');
var _ = require('underscore');
// methods
function sum(a,b) {
return a + b;
}
function multiply(a,b) {
return a * b;
}
function divide(a,b) {
return a / b;
}
function subtract(a,b) {
return a - b;
}
function updateResult() {
// use $ and _ to update something
}
// exposed public methods
module.exports = {
sum: sum,
multiply: multiply,
divide: divide,
subtract: subtract,
updateResult: updateResult
};
The above code is in the Common JS style. CommonJS is a style you will be
familiar with if worked in Node. It’s also been gaining popularity on the client
side with Browserify. Browserify is used to convert the common JS modules into a
browser consumable format since the module.exports cannot be resolved on the
client side unless a container object is created - what require JS does while it
wraps the AMD modules in the simplify common JS format.
There are libraries used on the server side and client side. If you don't make
your code compatible to both cases, then you'll find developers having trouble
of using it and resorting to shims to get your library working. Classic example
being - underscore.js in AMD. Underscore.js is not an AMD module and will have
to be shimmed to be used.
There are engineers that feel CommonJS is better suited to server-side
development which is one reason there's currently a level of disagreement over
which format should be used as the de-facto standard.
So, until then, while authoring libraries, its important that you satisfy
consumers of both these styles - at least till the near future where they decide
which is the spec. This gives rise to UMD (Universal Module Definition).
(function (window,factory) {
if (typeof define == 'function' && define.amd) {
// AMD
define(['jquery', 'underscore'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS
module.exports = factory(require('jquery'), require('underscore'));
} else {
// Browser globals on window
window.returnExports = factory(window.jQuery, window._);
}
}(this, function ($, _) {
// methods
function sum(a,b) {
return a + b;
};
function multiply(a,b) {
return a * b;
};
function division(a,b) {
return a / b;
};
function subtract(a,b) {
return a - b;
};
function updateResult() {
// use $ and _ to update something
};
// exposed public methods
return {
sum: sum,
multiply: multiply,
divide: divide,
subtract: subtract,
updateResult: updateResult
}
}));
This is a universal pattern that supports both the styles mentioned above. The
same module is now re-written below in the UMD format.
It is a bit of a clutter, but, your library supports both the worlds and all are
happy now!
AMD takes a browser-first approach, using asynchronous behavior and backwards
compatibility but doesn't have a File I/O concept. It supports objects,
functions, constructors, strings, JSON and many other types of modules,
running natively in the browser. It can be used to lazy load / defer the
loading of dependencies.
CommonJS on the other hand takes a server-first approach, assuming synchronous
behavior, no globals and it attempts to cater for the future - server side. So,
Common JS supports unwrapped modules, freeing you of the define() wrapper that
AMD enforces.
CommonJS modules were designed with server development in mind. Naturally, the
API is synchronous. In other words, modules are loaded at the moment and in the
order they are required inside a source file.
CommonJS Pros:
1. Simple: a developer can grasp the concept without looking at the docs.
2. Dependency management is integrated: modules require other modules and get
loaded in the needed order.
3. The require statement can be called anywhere and modules can be loaded
programmatically.
4. Circular dependencies are supported.
CommonJS Cons:
1. Synchronous API makes it not suitable for certain uses (client-side).
2. One file per module.
3. Browsers require a loader library or transpiling.
4. No constructor function for modules (Node supports this though).
5. Hard to analyze for static code analyzers.
For the client there are currently two popular options: webpack and browserify.
Browserify was explicitly developed to parse Node-like module definitions (many
Node packages work out-of-the-box with it!) and bundle your code plus the code
from those modules in a single file that carries all dependencies. Webpack on
the other hand was developed to handle creating complex pipelines of source
transformations before publishing. This includes bundling together CommonJS
modules.
AMD was born out of a group of developers that were displeased with the
direction adopted by CommonJS. In fact, AMD was split from CommonJS early in its
development. The main difference between AMD and CommonJS lies in its support
for asynchronous module loading.
AMD Pros:
1. Asynchronous loading (better startup times).
2. Circular dependencies are supported.
3. Compatibility for require and exports.
4. Dependency management fully integrated.
5. Modules can be split in multiple files if necessary.
6. Constructor functions are supported.
7. Plugin support (custom loading steps).
AMD Cons:
1. Slightly more complex syntactically.
2. Loader libraries are required unless transpiled.
3. Hard to analyze for static code analyzers.
Using require.js is pretty straightforward: include the library in your HTML
file and use the data-main attribute to tell require.js which module should be
loaded first.
Fortunately, the ECMA team behind the standardization of JavaScript decided to
tackle the issue of modules. The result can be seen in the latest release of the
JavaScript standard: ECMAScript 2015 (previously known as ECMAScript 6).
The result is syntactically pleasing and compatible with both synchronous and
asynchronous modes of operation.
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
The above code show a lib.js file. The name of the file probably does not
matter. Inside this file, we export two functions (square, and diag). Inside
the main.js file, we import these two functions and use them.
The import directive can be used to bring modules into the namespace. This
directive, in contrast with require and define is not dynamic (i.e. it cannot
be called at any place). The export directive, on the other hand, can be used to
explicitly make elements public.
The static nature of the import and export directive allows static analyzers to
build a full tree of dependencies without running code. ES2015 does support
dynamic loading of modules:
System.import('some_module')
.then(some_module => {
// Use some_module
})
.catch(error => {
// ...
});
In truth, ES2015 only specifies the syntax for the dynamic and static module
loaders. In practice, ES2015 implementations are not required to do anything
after parsing these directives. Module loaders such as System.js are still
required until the next ECMAScript spec is released.
This solution, by virtue of being integrated in the language, lets runtimes
pick the best loading strategy for modules. In other words, when asynchronous
loading gives benefits, it can be used by the runtime.
ES2015 Pros:
1. Synchronous and asynchronous loading supported.
2. Syntactically simple.
3. Support for static analysis tools.
4. Integrated in the language (eventually supported everywhere, no need for libraries).
5. Circular dependencies supported.
ES2015 Cons:
1. Still not supported everywhere. Fortunately many transpilers do support
modules and a polyfill is also available. Currently, the ES2015 preset for
Babel can handle modules with no trouble.
System.js: a universal module loader that supports CommonJS, AMD and ES2015
modules. It can work in tandem with transpilers such as Babel or Traceur and
can support Node and IE8+ environments. Using it is a matter of loading System.js
in your code and then pointing it to your base URL:
<script src="system.js"></script>
<script>
// set our baseURL reference path
System.config({
baseURL: '/app',
// or 'traceur' or 'typescript'
transpiler: 'babel',
// or traceurOptions or typescriptOptions
babelOptions: {
}
});
// loads /app/main.js
System.import('main.js');
</script>
As System.js does all the job on-the-fly, using ES2015 modules should generally
be left to a transpiler during the build step in production mode. When not in
production mode, System.js can call the transpiler for you, providing seamless
transition between production and debugging environments.
What are the available AMD libraries?
- curl.js: http://davidwalsh.name/curljs
- Jam: http://net.tutsplus.com/tutorials/javascript-ajax/frictionless-amd-with-jam/
- RequireJS
- Script.js: http://dustindiaz.com/scriptjs
- StackJS: http://www.position-absolute.com/articles/stackjs-a-javascript-module-loader-and-dependencies-handler/
- StackJS: http://blogs.sitepoint.com/2010/10/27/throwing-better-errors-using-stack
- YepNope: http://blogs.sitepoint.com/2011/03/08/regressive-enhancement-with-modernizr-and-yepnope/
- YepNope: http://net.tutsplus.com/tutorials/javascript-ajax/easy-script-loading-with-yepnope-js/





