
No module system -> CommonJS -> AMD -> CMD -> ES6 Modules
The CommonJS specification was introduced to address scope and modularity problems in JavaScript. It lets each module execute inside its own namespace. In practice, every file is treated as its own module and has its own scope. Variables, functions, and classes declared in one file are private to that file unless they are explicitly exported.
On the server side, CommonJS modules are loaded synchronously at runtime. In the browser, they usually need to be bundled ahead of time.
// export
module.exports = value;
exports.xxx = value;
// import
require(xxx);require is to load and execute a JavaScript file, then return that module's exports object.AMD stands for Asynchronous Module Definition. Its core idea is asynchronous module loading, so loading a module does not block the statements that follow it. Code that depends on a module is placed inside a callback and runs after the module finishes loading.
// module without dependencies
define(function () {
return "";
});
// module with dependencies
define(["module1", "module2"], function (m1, m2) {
// do something with m1 and m2
});require(["module1", "module2"], function (m1, m2) {
// do something with m1 and m2
});CMD is a module specification designed mainly for browsers. Module loading is asynchronous, and a module is typically loaded when it is actually used. CMD combines ideas from both CommonJS and AMD. In Sea.js, JavaScript modules generally follow the CMD style.
// module without dependencies
define(function (require, exports, module) {
exports.xxx = value;
module.exports = value;
});
// module with dependencies
define(function (require, exports, module) {
var module2 = require("./module2");
require.async("./module3", function (m3) {});
exports.xxx = value;
});define(function (require) {
var m1 = require("./module1");
var m4 = require("./module4");
m1.show();
m4.show();
});ES6 introduced modules at the language level and did so in a much more standardized way. The goal was to provide a common module solution for both browsers and servers.
The design of ES modules is intentionally static. The dependency graph, as well as imported and exported bindings, can be determined at compile time.
export style
let basicNum = 0;
let add = function (a, b) {
return a + b;
};
export { basicNum, add };import { basicNum, add } from "./math";
function test(ele) {
ele.textContent = add(99 + basicNum);
}export default style
// export-default.js
export default function () {
console.log("foo");
}The default export of export-default.js is a function. Other modules can import it using any name they want.
// import-default.js
import customName from "./export-default";
customName(); // fooWith a default export, you do not use curly braces when importing.
export vs export default export and import can appear multiple times, but export default can only appear once in a module.{}.{}.export can directly export variables and bindings by name.Anything with an s, such as exports and module.exports, belongs to CommonJS. The singular forms export and export default belong to ES modules.
import and creates a binding to the exported value. When the code runs, the imported name points back to the original binding in the source module.export, and import uses static syntax to consume them.In short:
module.exports after the module has executed.That difference is fundamental to modern bundling, tree-shaking, and static analysis.