The JS module specification (CommonJS, AMD, CMD). If you’ve heard of JS modularity, you’ve probably heard of CommonJS or AMD or even CMD. If only some basic work, we are familiar with its use, but we can not just hazy about a piece, today I will tidy up, what is it? How do they work on our front end?

CommonJs

CommonJS is the specification for how JS should behave. NodeJS is the implementation of this specification, and WebPack is written in CommonJS. Because JS doesn’t have the functionality of a module, CommonJS was born because it wants JS to run anywhere, not just in the browser. Its ultimate goal is to provide a standard library similar to Python, Ruby, and Java.

If you’ve written on the Node.js platform, you should be familiar with the CommonJS specification. Unlike the previous AMD and CMD specifications, the CommonJS specification is generally applied to the server (node.js platform), and CommonJS modules are loaded synchronously (depending on the scenario). At the same time, thanks to third-party tools like Browserify, we can use CommonJS files on the browser side.

CommonJS defines modules as :{module reference} {module definition (exports)} {module identity (module)} require() to import external modules; Exports objects are used to export methods or variables of the current module, unique export; The Module object represents the module itself.Copy the code

Although Node follows the CommonJS specification, there are some trade-offs and some new additions.

However, having said CommonJS and Node, I think it’s important to understand NPM first. NPM is the package manager for Node, and it’s supposed to follow the CommonJS specification. It’s supposed to follow the package specification (and the theory).

CommonJS is designed primarily for the back end of JS, so why isn’t it suitable for the front end?

Let’s see how it works:

The root cause of browser incompatibility with CommonJS is the lack of four node.js environment variables. module exports require globalCopy the code

As long as these four variables are available, the browser can load the CommonJS module.

Once you know how it works, you can make tools. Browserify is currently the most commonly used tool for CommonJS format conversion. (Interested students can go to further understanding)

AMD

With nodeJS based on the commonJS specification, the concept of server modules has been formed, and it is natural that people want client modules. And preferably compatible, one module will run on both the server and the browser without modification. However, there is a major limitation that makes the CommonJS specification unsuitable for the browser environment. If you look at the following code, if you run it in a browser, there is a big problem. Can you tell?

var math = require('math');
math.add(2, 3);
Copy the code

The second line math.add(2, 3) runs after the first line require(‘math’), so must wait for math.js to finish loading. That is, if it takes a long time to load, the entire application will just sit there and wait. You’ll notice that require is synchronized. This is not a problem on the server because all modules are stored on the local hard disk and can be loaded synchronously, and the wait time is the hard disk read time. For browsers, however, this is a big problem because modules are on the server side and the wait time can be long depending on the speed of the network, leaving the browser in a state of “suspended animation”.

Therefore, browser-side modules cannot be synchronous, they can only be asynchronous. This is the background from which the AMD specification was born.

CommonJS is mainly for the performance of JS in the back end, it is not suitable for the front end, AMD(asynchronous module definition) emerged, it is mainly for the performance of front-end JS specification

AMD stands for “Asynchronous Module Definition”. It loads modules asynchronously without affecting the execution of subsequent statements. All statements that depend on this module are defined in a callback function that will not run until the load is complete.

AMD also uses the require() statement to load modules, but unlike CommonJS, it requires two arguments:

require([module], callback);
Copy the code

The first argument, [module], is an array whose members are the modules to be loaded. The second argument, callback, is the callback function after the successful loading. If you rewrite the previous code to AMD form, it looks like this:

require(['math'].function (math) {
    math.add(2, 3);
});
Copy the code

Math.add () is not synchronized with the Loading of the Math module, and the browser does not fake death. So clearly, AMD is a good fit for the browser environment. Currently, there are two major Javascript libraries that implement the AMD specification: require.js and curl.

Require.js was created to solve these two problems:

(1) Realize asynchronous loading of JS files to avoid losing response of web pages; (2) Manage the dependency between modules to facilitate code writing and maintenance.

Of course, I think every library has its own value.

AMD has only one interface: DEFINE (ID? ,dependencies? ,factory);

It will specify all dependencies (DEPs) when declaring the module and pass them to the factory as parameters, like this:

define(['dep1'.'dep2'].function(dep1,dep2){... });Copy the code

If there are no dependencies, define simple modules like this:

define(function(){
    var exports = {}; 
    exports.method = function() {... };return exports;
});
Copy the code

The Node implementation has the define keyword wrapped around the object. The Node implementation has the define keyword wrapped around the object…..

This has AMD WIKI Chinese version, said a lot of pretty detailed things, use of time can view: AMD WIKI Chinese version

CMD

The CMD specification, which stands for “Common Module Definition”, is called the generic Module loading specification. It is also used on the browser side. The browser-side asynchronous loading library sea-.js implements the CMD specification.

AMD/CMD difference, although are parallel loading JS files, but there is a difference, AMD is preloading, in parallel loading JS files at the same time, will also parse the execution of the module (because it also needs to be executed, so before loading a module, the module dependent module needs to be loaded first); CMD, on the other hand, is lazy, loading js files in parallel at the beginning, but not executed, but only executed when needed.

In the CMD specification, a module is a file

define(id? , deps? , factory)Copy the code
Id: module identifier DEps: module dependent Factory: can be a function, an object or a string.Copy the code

For more detailed specifications, refer to the CMD specification

ES6 Module

ES6, on the level of language standards, implements module functions, and implements them quite simply, aiming to become a common module solution for browsers and servers. Its module functions are mainly composed of two commands: export and import. The export command is used to specify the external interface of a module, and the import command is used to input functions provided by other modules.

Math.js **/ var basicNum = 0; var add = function (a, b) { return a + b; }; export { basicNum, add }; /** reference module **/ import {basicNum, add} from './math'; function test(ele) { ele.textContent = add(99 + basicNum); }Copy the code

As shown in the example above, when using the import command, the user needs to know the name of the variable or function to be loaded. In fact, ES6 also provides the export default command, which specifies the default output of the module. The corresponding import statement does not need curly braces. This is also closer to ADM’s citation style.

/ * *exportDefault **/ / define the outputexportdefault { basicNum, add }; // Import math from'./math';
function test(ele) {
    ele.textContent = math.add(99 + math.basicNum);
}
Copy the code

ES6 modules are not objects, and the import command is statically analyzed by the JavaScript engine. The module code is introduced at compile time, rather than loaded at run time, so conditional loading cannot be implemented. Because of this, static analysis is possible.

Differences between ES6 modules and CommonJS modules

1. The CommonJS module outputs a copy of a value, while the ES6 module outputs a reference to a value.

  1. The CommonJS module outputs a copy of the value, meaning that once a value is output, changes within the module do not affect that value.
  2. ES6 modules operate differently from CommonJS. When the JS engine statically analyzes a script, it generates a read-only reference to the module load command import. When the script is actually executed, it will be evaluated in the loaded module based on the read-only reference. In other words, the IMPORT of ES6 is a bit like the “symbolic link” of Unix systems, where the original value changes and the import load value changes with it. Therefore, ES6 modules are referenced dynamically and do not cache values. Variables in modules are bound to the module in which they are located

2. CommonJS module is run time loading, ES6 module is compile time output interface.

1. Runtime loading: CommonJS modules are objects; That is, the entire module is loaded on input, an object is generated, and methods are read from that object. This loading is called “runtime loading.”

2. Compile-time loading: ES6 modules are not objects. Instead, they are output code explicitly specified by the export command, and static commands are used for import. That is, when you import, you can specify that an output value is loaded instead of the entire module, which is called “compile-time loading.”

CommonJS loads an object (that is, the module.exports property) that is generated only after the script runs. An ES6 module is not an object, and its external interface is a static definition that is generated during the code static parsing phase.

What is omitted, welcome to supplement ~