I've been working with AMD modules and RequireJS quite a bit lately and I'm trying to figure out exactly what the AMD spec is. So far the only thing I've been able to find is the amdjs GitHub page at https://github.com/amdjs/amdjs-api/wiki/AMD.
This page only shows the define( id, dependencies, factory) function as part of the official spec. Require has another function called require( dependencies, callback ) and I'm not sure if its part of the official spec or if its just a conviennece function provided by the RequireJS library.
From the page you linked, under the heading Global Variables:
This specification reserves the global variable "define" for use in
implementing this specification, the package metadata asynchronous
definition API and is reserved for other future CommonJS APIs. Module
loaders SHOULD not add additional methods or properties to this
function.
This specification reserves the global variable "require" for use by
module loaders. Module loaders are free to use this global variable as
they see fit. They may use the variable and add any properties or
functions to it as desired for module loader specific functionality.
They can also choose not to use "require" as well.
Curl is an example of an AMD loader that doesn't use require.
In addition there is a page that details the require API for loaders that support it.
Related
I'm still very confused about CommonJS, AMD and RequireJS, even after reading a lot.
I know that CommonJS (formerly ServerJS) is a group for defining some JavaScript specifications (i.e. modules) when the language is used outside the browser. CommonJS modules specification has some implementation like Node.js or RingoJS, right?
What's the relation between CommonJS, Asynchronous Module Definition (AMD) and RequireJS?
Is RequireJS an implementation of the CommonJS module definition? If yes, what's AMD then?
RequireJS implements the AMD API (source).
CommonJS is a way of defining modules with the help of an exports object, that defines the module contents. Simply put, a CommonJS implementation might work like this:
// someModule.js
exports.doSomething = function() { return "foo"; };
//otherModule.js
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
Basically, CommonJS specifies that you need to have a require() function to fetch dependencies, an exports variable to export module contents and a module identifier (which describes the location of the module in question in relation to this module) that is used to require the dependencies (source). CommonJS has various implementations, including Node.js, which you mentioned.
CommonJS was not particularly designed with browsers in mind, so it doesn't fit in the browser environment very well (*I really have no source for this--it just says so everywhere, including the RequireJS site.*) Apparently, this has something to do with asynchronous loading, etc.
On the other hand, RequireJS implements AMD, which is designed to suit the browser environment (source). Apparently, AMD started as a spinoff of the CommonJS Transport format and evolved into its own module definition API. Hence the similarities between the two. The new feature in AMD is the define() function that allows the module to declare its dependencies before being loaded. For example, the definition could be:
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
return ModuleContents;
});
So, CommonJS and AMD are JavaScript module definition APIs that have different implementations, but both come from the same origins.
AMD is more suited for the browser, because it supports asynchronous loading of module dependencies.
RequireJS is an implementation of AMD, while at the same time trying to keep the spirit of CommonJS (mainly in the module identifiers).
To confuse you even more, RequireJS, while being an AMD implementation, offers a CommonJS wrapper so CommonJS modules can almost directly be imported for use with RequireJS.
define(function(require, exports, module) {
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});
CommonJS is more than that - it's a project to define a common API and ecosystem for JavaScript. One part of CommonJS is the Module specification. Node.js and RingoJS are server-side JavaScript runtimes, and yes, both of them implement modules based on the CommonJS Module spec.
AMD (Asynchronous Module Definition) is another specification for modules. RequireJS is probably the most popular implementation of AMD. One major difference from CommonJS is that AMD specifies that modules are loaded asynchronously - that means modules are loaded in parallel, as opposed to blocking the execution by waiting for a load to finish.
AMD is generally more used in client-side (in-browser) JavaScript development due to this, and CommonJS Modules are generally used server-side. However, you can use either module spec in either environment - for example, RequireJS offers directions for running in Node.js and browserify is a CommonJS Module implementation that can run in the browser.
The short answer would be:
CommonJS and AMD are specifications (or formats) on how modules and their dependencies should be declared in javascript applications.
RequireJS is a script loader library that is AMD compliant, curljs being another example.
CommonJS compliant:
Taken from Addy Osmani's book.
// package/lib is a dependency we require
var lib = require( "package/lib" );
// behavior for our module
function foo(){
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
exports.foobar = foo;
AMD compliant:
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
Somewhere else the module can be used with:
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
Some background:
Actually, CommonJS is much more than an API declaration and only a part of it deals with that. AMD started as a draft specification for the module format on the CommonJS list, but full consensus wasn't reached and further development of the format moved to the amdjs group. Arguments around which format is better state that CommonJS attempts to cover a broader set of concerns and that it's better suited for server side development given its synchronous nature, and that AMD is better suited for client side (browser) development given its asynchronous nature and the fact that it has its roots in Dojo's module declaration implementation.
Sources:
RequireJS - Why AMD?
Addy Osmani - Learning JavaScript Design Patterns - Modern Modular JavaScript Design Patterns
Quoting
AMD:
One browser-first approach
Opting for asynchronous behavior and simplified backwards compatibility
It doesn't have any concept of File I/O.
It supports objects, functions, constructors, strings, JSON and many other types of modules.
CommonJS:
One server-first approach
Assuming synchronous behavior
Cover a broader set of concerns such as I/O, File system, Promises and more.
Supports unwrapped modules, it can feel a little more close to the ES.next/Harmony specifications, freeing you of the define() wrapper that AMD enforces.
Only support objects as modules.
It is quite normal to organize JavaScript program modular into several files and to call child-modules from the main js module.
The thing is JavaScript doesn't provide this. Not even today in latest browser versions of Chrome and FF.
But, is there any keyword in JavaScript to call another JavaScript module?
This question may be a total collapse of the world for many because the answer is No.
In ES5 ( released in 2009 ) JavaScript had no keywords like import, include, or require.
ES6 saves the day ( released in 2015 ) proposing the import keyword ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import ), and now all modern browsers support this.
If you use Babel 6.18.0 and transpile with ES2015 option only
import myDefault from "my-module";
you will get require again.
"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
This is because require means the module will be loaded from Node.js. Node.js will handle everything from system level file read to wrapping functions into the module.
Because in JavaScript functions are the only wrappers to represent the modules.
I'm a lot confused about CommonJS and AMD?
Both CommonJS and AMD are just two different techniques how to overcome the JavaScript "defect" to load modules smart.
AMD
introduced in JavaScript to scale JavaScript project into multiple files
mostly used in browser based application and libraries
popular implementation is RequireJS, Dojo Toolkit
CommonJS:
it is specification to handle large number of functions, files and modules of big project
initial name ServerJS introduced in January, 2009 by Mozilla
renamed in August, 2009 to CommonJS to show the broader applicability of the APIs
initially implementation were server, nodejs, desktop based libraries
Example
upper.js file
exports.uppercase = str => str.toUpperCase()
main.js file
const uppercaseModule = require('uppercase.js')
uppercaseModule.uppercase('test')
Summary
AMD – one of the most ancient module systems, initially implemented by the library require.js.
CommonJS – the module system created for Node.js server.
UMD – one more module system, suggested as a universal one, compatible with AMD and CommonJS.
Resources:
https://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript
Wikipedia
I have several JavaScript files in my web application which were previously loaded through <script> tags, in order of relative dependencies. Now I'm re-organizing them through require.js in order to accumulate and minify them for production.
For starters, I'd like to simply load all files into the global (window) context, without AMD encapsulation yet:
require([
'jquery'], function() {
require([
'jquery-ui'], function() {
require([
'jquery-ui.touch-punch',
// [...]
]);
});
});
The idea here is that 'jquery' defines a global (window context) jQuery variable, 'jquery-ui' sets jQuery.ui and 'jquery-ui.touch-punch' alters jQuery.ui (for better touch support).
This works well when running as is, i.e. without optimization. However, after compiling into one file and minifying using the RequireJS optimizer, the following error occurs:
Uncaught TypeError: Cannot read property 'mouse' of undefined
This happens on a line trying to access jQuery.ui.mouse.
Inside the browser console, jQuery is correctly set in the window context, but jQuery.ui is undefined.
However, manually executing require(['jquery-ui']) does set jQuery.ui as expected.
It seems like jQuery UI behaves differently after optimization, but I can't see how exactly or why. What am I doing wrong?
The Scoop
Set the dependencies between non-AMD modules using shim rather than through nested require calls (which do not in fact set dependencies). Make sure also to use wrapShim: true in the configuration you give r.js.
Explanation
One or more of the modules you are trying to load are not AMD modules, but you are not actually defining dependencies between your non-AMD modules.
When you nest require calls like you do, you are coercing the order in which some modules are loaded at run time, but this does not actually establish a dependency between modules. So this strategy works as long as the modules are not optimized but may fail after optimization.
There are only two ways to establish dependencies:
By passing an array of dependencies to a define call. This method is used by modules actually written for the AMD spec. (RequireJS also supports using the CommonJS way of requiring modules but behind the scenes, it is transformed to a define call with an array of dependencies. So it does not constitute a 3rd way.)
By setting a shim which list dependencies. This method is for non-AMD modules.
If you don't set a shim, then the optimizer is free to order the non-AMD modules in whichever order it wants. jquery-ui.touch-punch could appear before jquery-ui and jquery in the optimized file, because there's no reason it shouldn't, and then you'd run into trouble. If you look at the code of this plugin, you see that it is not AMD-aware. It just expects jQuery and jQuery UI to be present and will fail if they are not present.
When you do set a shim, then you coerce the order of the non-AMD modules in the optimized file.
You need wrapShim because the jquery-ui.touch-punch when using an AMD-aware version of jQuery UI. Otherwise, jQuery UI's factory won't be run before the plugin needs it.
I'm working on a legacy app in durandal. I noticed when I define a module:
define({
message: 'hello world'
});
Then the output from grunt looks like:
define('filePath\fileName',{
message: 'hello world'
});
Where does filePath\fileName come from? I tried building a module in plain RequireJS and I had to supply this id myself. I read that Durandal uses a pattern called AMD (Asynchronous Module Definition pattern). Is the filePath\fileName using fileName.js convention a part of the AMD pattern?
AMD optimizers add these ids when they optimize your modules.
As long as you have one module per file, an AMD loader is able to infer the module id from the path of the file and from the configuration of the module loader. So it is okay when you have one module per file to omit the module id from the define call, and let the AMD loader infer the module id. This is called an "anonymous define, by the way.
One of the jobs of the optimizer is to combine multiple modules in a single file. When the optimizer combines multiple modules in the same file, then there's no way to distinguish which define call belongs to which module, unless the optimizer also records this information. The way the AMD specification is designed, the way to record which define belongs to which module is to add the module id as the first argument of define.
I'm still very confused about CommonJS, AMD and RequireJS, even after reading a lot.
I know that CommonJS (formerly ServerJS) is a group for defining some JavaScript specifications (i.e. modules) when the language is used outside the browser. CommonJS modules specification has some implementation like Node.js or RingoJS, right?
What's the relation between CommonJS, Asynchronous Module Definition (AMD) and RequireJS?
Is RequireJS an implementation of the CommonJS module definition? If yes, what's AMD then?
RequireJS implements the AMD API (source).
CommonJS is a way of defining modules with the help of an exports object, that defines the module contents. Simply put, a CommonJS implementation might work like this:
// someModule.js
exports.doSomething = function() { return "foo"; };
//otherModule.js
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
Basically, CommonJS specifies that you need to have a require() function to fetch dependencies, an exports variable to export module contents and a module identifier (which describes the location of the module in question in relation to this module) that is used to require the dependencies (source). CommonJS has various implementations, including Node.js, which you mentioned.
CommonJS was not particularly designed with browsers in mind, so it doesn't fit in the browser environment very well (*I really have no source for this--it just says so everywhere, including the RequireJS site.*) Apparently, this has something to do with asynchronous loading, etc.
On the other hand, RequireJS implements AMD, which is designed to suit the browser environment (source). Apparently, AMD started as a spinoff of the CommonJS Transport format and evolved into its own module definition API. Hence the similarities between the two. The new feature in AMD is the define() function that allows the module to declare its dependencies before being loaded. For example, the definition could be:
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
return ModuleContents;
});
So, CommonJS and AMD are JavaScript module definition APIs that have different implementations, but both come from the same origins.
AMD is more suited for the browser, because it supports asynchronous loading of module dependencies.
RequireJS is an implementation of AMD, while at the same time trying to keep the spirit of CommonJS (mainly in the module identifiers).
To confuse you even more, RequireJS, while being an AMD implementation, offers a CommonJS wrapper so CommonJS modules can almost directly be imported for use with RequireJS.
define(function(require, exports, module) {
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});
CommonJS is more than that - it's a project to define a common API and ecosystem for JavaScript. One part of CommonJS is the Module specification. Node.js and RingoJS are server-side JavaScript runtimes, and yes, both of them implement modules based on the CommonJS Module spec.
AMD (Asynchronous Module Definition) is another specification for modules. RequireJS is probably the most popular implementation of AMD. One major difference from CommonJS is that AMD specifies that modules are loaded asynchronously - that means modules are loaded in parallel, as opposed to blocking the execution by waiting for a load to finish.
AMD is generally more used in client-side (in-browser) JavaScript development due to this, and CommonJS Modules are generally used server-side. However, you can use either module spec in either environment - for example, RequireJS offers directions for running in Node.js and browserify is a CommonJS Module implementation that can run in the browser.
The short answer would be:
CommonJS and AMD are specifications (or formats) on how modules and their dependencies should be declared in javascript applications.
RequireJS is a script loader library that is AMD compliant, curljs being another example.
CommonJS compliant:
Taken from Addy Osmani's book.
// package/lib is a dependency we require
var lib = require( "package/lib" );
// behavior for our module
function foo(){
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
exports.foobar = foo;
AMD compliant:
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
Somewhere else the module can be used with:
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
Some background:
Actually, CommonJS is much more than an API declaration and only a part of it deals with that. AMD started as a draft specification for the module format on the CommonJS list, but full consensus wasn't reached and further development of the format moved to the amdjs group. Arguments around which format is better state that CommonJS attempts to cover a broader set of concerns and that it's better suited for server side development given its synchronous nature, and that AMD is better suited for client side (browser) development given its asynchronous nature and the fact that it has its roots in Dojo's module declaration implementation.
Sources:
RequireJS - Why AMD?
Addy Osmani - Learning JavaScript Design Patterns - Modern Modular JavaScript Design Patterns
Quoting
AMD:
One browser-first approach
Opting for asynchronous behavior and simplified backwards compatibility
It doesn't have any concept of File I/O.
It supports objects, functions, constructors, strings, JSON and many other types of modules.
CommonJS:
One server-first approach
Assuming synchronous behavior
Cover a broader set of concerns such as I/O, File system, Promises and more.
Supports unwrapped modules, it can feel a little more close to the ES.next/Harmony specifications, freeing you of the define() wrapper that AMD enforces.
Only support objects as modules.
It is quite normal to organize JavaScript program modular into several files and to call child-modules from the main js module.
The thing is JavaScript doesn't provide this. Not even today in latest browser versions of Chrome and FF.
But, is there any keyword in JavaScript to call another JavaScript module?
This question may be a total collapse of the world for many because the answer is No.
In ES5 ( released in 2009 ) JavaScript had no keywords like import, include, or require.
ES6 saves the day ( released in 2015 ) proposing the import keyword ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import ), and now all modern browsers support this.
If you use Babel 6.18.0 and transpile with ES2015 option only
import myDefault from "my-module";
you will get require again.
"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
This is because require means the module will be loaded from Node.js. Node.js will handle everything from system level file read to wrapping functions into the module.
Because in JavaScript functions are the only wrappers to represent the modules.
I'm a lot confused about CommonJS and AMD?
Both CommonJS and AMD are just two different techniques how to overcome the JavaScript "defect" to load modules smart.
AMD
introduced in JavaScript to scale JavaScript project into multiple files
mostly used in browser based application and libraries
popular implementation is RequireJS, Dojo Toolkit
CommonJS:
it is specification to handle large number of functions, files and modules of big project
initial name ServerJS introduced in January, 2009 by Mozilla
renamed in August, 2009 to CommonJS to show the broader applicability of the APIs
initially implementation were server, nodejs, desktop based libraries
Example
upper.js file
exports.uppercase = str => str.toUpperCase()
main.js file
const uppercaseModule = require('uppercase.js')
uppercaseModule.uppercase('test')
Summary
AMD – one of the most ancient module systems, initially implemented by the library require.js.
CommonJS – the module system created for Node.js server.
UMD – one more module system, suggested as a universal one, compatible with AMD and CommonJS.
Resources:
https://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript
Wikipedia
Hello with RequireJS I can set a base path like this: base : './app/' so when I am in ./app/foo/bar/ for example and I have a script where I use require('foo'); RequireJS then would search for ./app/foo.js and not in node_module folder or in ./app/foo/bar/foo.js this comes handy when you have a kind of structure where it would be much cleaner for you as a developer to see the dependencies instead of having ../../foo.js. I could have ./app/foo.js and ./app/foo/foo.js and ./app/foo/bar/foo.js it would be much more cleaner to have:
require('foo');
require('foo/foo');
require('foo/bar/foo');
rather than:
require('../../foo');
require('../foo');
require('./foo');
Now you could say why not change the name and not have foo everywhere, let's say that we can't for any reason…
Another lack of feature that I see in node's require method against RequireJS is the ability of setting path mapping, if I have a directory named ./app/super-sized-directory-name/ in RequireJS I could simply do 'big-dir' : 'super-sized-directory-name' and then I could simply use require('./app/big-dir/foo') with Node.js's require method this is not possible as far as I know…
--alias, -a Register an alias with a colon separator: "to:from"
Example: --alias 'jquery:jquery-browserify'
You can register aliases with browserify, so that covers your renaming.
As for your rooted absolute paths, that can't really be done. As mentioned modul8 has a namespacing mechanism to solve this.
I would recommend you pong SubStack in #stackvm on freenode and ask him directly.
It may or may not help you, but I believe the Dojo Frameworks AMD Loader is API compatible with RequireJS and providing you are using a new microkernel does not pollute the global namespace.
I believe it only has require() and define() in the global namespace now.
Anyway their method of dealing with this is to do something like:
require(["dojo/node!util"], function(util){
// Module available as util
});
The documentation is at http://dojotoolkit.org/reference-guide/1.8/dojo/node.html
Use uRequire which provides a 'bridge' between nodejs require and AMD define modules, without reinventing the wheel (it is build on top of the two standards). It basically converts modules from AMD or commonJS format to the other format or UMD that runs smoothly on both nodejs & the browser.
It is also translating dependency paths with flexible path conventions, so you can have either '../../foo' or 'bar/foo' depending on which makes more sense at the point you are at.
Your AMD or UMD modules are loaded asynchronously on browser (using AMD/requireJs or other AMD loader) and on node the asynchronous require(['dep1', 'dep2'], function(dep1,dep2){...}) is also simulated.