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
Related
I am trying to answer,
when to use import/export and when to use require()/module.exports? But as I try to dig, it seems to get complicated.
Here's my understanding
require()/module.exports: this is nodejs implementation of the module system. This loads the modules syncronously.
with es6, we can use import/export. the docs says
The import statement is used to import bindings which are exported by another module. Imported modules are in strict mode whether you declare them as such or not. The import statement cannot be used in embedded scripts unless such script has a type="module".
Ques1: How does this work with babel or webpack or browsers in general?
As I was exploring I came across stuff like CommonJs, requireJs, Asynchronous Module Definition (AMD)
Ques2: I am more interested in knowing the timeline as how these things evolved in javascript ?
How does this work with babel or webpack or browsers in general?
Babel and Webpack follow the ES spec and transpile the import / export statement to one single file. As they also support the require syntax, they usually transpile the import statements to require() calls and the export statements to module exports, and then ship with a custom loader for modules., If you got for example:
// A.js
export default function() { }
// B.js
import A from "./A";
A();
Then it gets transpiled to the following require syntax:
//A.js
exports.default = function() {};
//B.js
var A = require("./A").default;
A();
That could then get wrapped to something like:
(function() { // prevent leaking to global scope
// emulated loader:
var modules = {};
function require(name) { return modules[name]; }
function define(name, fn) {
var module = modules[name] = { exports: {} };
fn(module, module.exports, require);
}
// The code:
define("A", function(module, exports, require) {
// A.js
exports.default = function() { };
});
define("B", function(module, exports, require) {
// B.js
var A = require("A").default;
A();
});
})();
how these things evolved in javascript ?
A few years ago, writing JS was restricted to browsers, and the only way to load multiple js sources was to use multiple <script> tags and use the global object to exchange functionality. That was ugly.
Then Nodejs was invented and they needed a better way to work with modules and invented the require() thing.
The writers of the spec saw a need for a native syntax for that, so import / export were introduced.
Babel and others then wrote transpilers.
What webpack the bundler does is the following:
You specify an input file in the config
You specify an output file the config
Webpack will look at all the files which the input file requires (commomJS module system) or imports (ES6 module system). It then funnels the code based on file name extention through loaders. Loaders can transpile the individual files to code the browser can understand. An example of a loader is babel or the sass/scss compiler.
After the different files are transpiled with loaders, the plugins can work at the
transform the bundle of generated code into something else. The bundle is just a bunch of code which together forms piece of functionality
In won't go into detail in the internals of webpack too deeply, but the most important thing to understand is:
You use webpack so you can use split up your code in multiple files, which makes them more maintainable and easier to work with. However then requesting all these files by the client would be horrible for performance (many HTTP requests overhead). Therefore, we bundle the files into one file, or a couple so this overhead is reduced.
Generally, you should write all modern code with import/export syntax if you are using a bundler like webpack, or translating with Babel... npm modules may favor require/module syntax but you can still import them.
Also worth noting is the import() method which returns a promise that should resolve to the root module being imported asynchronously. Webpack may bundle these as asynchronous modules if you have it configured to do so.
In practice the resolution through tooling like babel and webpack will fallback to node-style behaviors against the node_modules lookup, where the standard is transport paths, favoring relative paths. Additional support is per environment.
You can experiment with esm support in modern browsers and in current node (behind a flag as of this answer). The behaviors are somewhat inconsistent, but well defined. When in doubt, experiment and try.
I don't like the whole export/require stuff in node, it takes too long. Let's say I have a file server.js and I want to use functions in whatever.js. in html I just add this to the header:
<script src='whatever.js'></script>
and then I can just use all the functions of whatever.js in my body's script.
But in node, in the server.js file I'd do:
var myobject = require('./whatever.js');
but then I need to set it to myobject, and further I need to go to whatever.js and manually decide what functions I want to export. not to mention that typing myobject.someFunction() is alot longer to write than someFunction() and I need to remember what I exposed/didn't expose.
I wanted something where I could just go:
require('./whatever.js');
and it puts it ALL in global, no bs. like in good old html/javascript. Is there a way to do this in node?
This will do the trick,
var fs = require('fs');
eval(fs.readFileSync('whatever.js')+'');
// here call functions from whatever.js file
(I realize this is an old thread but wanted to leave a note here for posterity.)
Here in 2022 there are several approaches for executing code from different files with Node.js:
ESM: Use standard ECMAScript modules
At the time of this writing, much of the node ecosystem (i.e. packages on npm) is in the process of transitioning to this paradigm, and there are some associated growing pains (e.g. things like __dirname are only available in CJS not ESM, though the workaround is easy).
For most developers, it would be advisable to become comfortable with this standard as it transcends node.js (i.e. is implemented in other runtimes like Deno and web browsers) and has been years in the making.
CJS: Use the original "CommonJS" module mechanism, e.g. require('./some-script.js')
It should be noted, particularly for the OP, that even though the "intended" way to use CJS modules is to export functions, constants, etc. and import them explicitly, it is possible to define everything in global scope using globalThis, though I would not recommend this.
// my-script.js
require('./foo.js');
require('./bar.js');
foo(); // This is foo from <...>foo.js
console.log(`bar = ${bar} (in ${__filename})`); // bar = 123 (in <...>my-script.js)
// foo.js
globalThis.foo = function() {
console.log(`This is foo from ${__filename}`);
}
// bar.js
globalThis.bar = 123;
If you try omitting globalThis. you'll find that foo and bar are no longer defined in the main script because require "wraps them" in "module scope."
Use eval
In my experience, there are very few legitimate use cases for eval (see Never use eval()!). Nevertheless, the functionality requested in this question is precisely what eval provides: "run some code as if it were written right here" and you can feed it from a file, as explained above by Mehul Prajapati
// include.js
// Defines a global function that works like C's "#include" preprocessor directive
const { readFileSync } = require('fs');
globalThis.include = function(scriptFile) {
console.warn('!!! EXTREMELY INSECURE !!!');
eval(readFileSync(scriptFile, 'utf-8'));
};
// main.js
require('./include.js'); // loads global include
// (I sure hope you completely trust these sources)
include('./foo.js');
include('./bar.js');
Note: Something that has contributed to much of my confusion in the past is that there have been competing standards/conventions/APIs that use some of the same identifiers, namely require, which require.js and other bundlers that support AMD (Asynchronous Module Definition)
use with different semantics. So for someone building a web application (using AMD for modules in web browsers) with node.js tooling (using CJS for modules locally) it can be frustrating to keep the functions straight, especially if it's an Electron application, which can expose Node.js APIs to scripts running in the renderer (browser). If you find yourself confused why a module is "not found" in a situation like that, check the stack trace to see which require is being called (and you may have to wrap/rename them on globalThis or something to avoid collisions).
Further reading:
JavaScript Modules: A Brief History [2019]
How the module system, CommonJS & require works [updated 2022]
What is AMD, CommonJS, and UMD? [2014]
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'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.
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.