JS itself is a versatile language, one that can compile itself with a high degree of freedom. Because of this freedom, there is a hype of norms and frameworks, one of the most basic is Module.

CommonJS·AMD·CMD·UMD·ES6, CommonJS·AMD·CMD·UMD·ES6

Note: this article is my subjective description of cheerful off-line cognition, which may differ from the history of the formation of real modules.

The root of everything

JS is a highly liberal language, even without the concept of modules. Similar concepts to modules can also be implemented by IIFE, new an object. It can also be reusable, scope-independent and easy to maintain. Such bulk, unable to maintain dependencies between modules. In a JS file, a module more than one, perhaps is the shura field.

The birth of the Module

So JS Module, a noun that people love and hate was born. JS itself is not designed with the concept of modules. Later, in order to make JS into a powerful language, industry leaders have done their best to set up a specification named CommonJS, which implements a thing called modules. Unfortunately, most browsers do not support it, and it can only be used for NodeJS. Therefore, CommonJS began to split and mutated a module named AMD specification, which can be used in the browser side. As AMD was far from CommonJS specification, AMD launched its own portal and requireJS framework. Used to implement and promote AMD specifications. Because AMD is so different from CommonJS and is used in different environments, UMD was born to be compatible with both platforms, but I think it is only a polyfill to be compatible with both platforms. At this point, CommonJS supporters decided that the browser could also implement the CommonJS specification, so they made a few changes to form the CMD specification and launched seaJS framework. ECMAScript6 defines a module loading function for JS. ES6 says, “Don’t debate, JS modules have native syntax.”

Real norms

Of the many specifications, only CommonJS and ES6 import/export are true specifications, while the rest are simulated environments that use existing JS support methods to implement their respective specifications.

As for why CommonJS and ES6 import/export are true specifications? Because only native support for their syntax can implement their specification.

CommonJS must have support from require and Module. exports to run. This is the main reason why browsers don’t work with CommonJS.

As for ES6, without support for the import and export keywords, everything is zero. For example, nodeJS does not support import and export. Nodejs supports other ES6 syntaxes, so it is not friendly to import and export. I think nodeJS implements the commonJS specification. Therefore, it is unacceptable for ES6 modules to interfere with nodeJS module specifications.

So CommonJS and ES6 modules are the real specifications.

I have written an article about CommonJS and ES6 modules in the past, so I won’t go into details here.

About how browsers implement CommonJS modules

Since the browser is missing two CommonJS keywords, the module is not valid, so create a module environment. Use the define method to internally emulate the CommonJS environment, providing the require and module.export methods. Both SeaJS and Requirejs implement modules by defining mock environments.

AMD on its own

When I was choosing A video card for my DIY desktop computer, I hesitated between A card and N card, but decided to choose A card because it was cheaper. Here A card refers to AMD, so and here JS AMD has A social relationship? It doesn’t matter! It is just a beautiful coincidence that the abbreviation of AMD for JS module is consistent with the name of AMD company in the United States.

Asynchronous Module Definition AMD is an Asynchronous Module Definition that requires all packages to be loaded and executed. Whether it works or not is out of AMD’s question. Requirejs stands for AMD:

Critical hits from AMD:

define("module1".function(require) {
    'use strict';
    console.log("cccc")}); define("module2".function(require) {
    'use strict';
    console.log("aaaa")
    if(false){
        console.log(require("module1"))
    }
    console.log("bbbb")}); require(["module2"])
Copy the code

CCCC, AAAA, BBBB, aAAA, BBBB, CCCC, AAAA, BBBB, CCCC, AAAA, BBBB, BBBB, CCCC, AAAA, BBBB, BBBB, CCCC, AAAA, BBBB

define("module1".function(require) {
    'use strict';
    console.log("cccc")}); define("module2",[module1],function(module1) {
    'use strict';
    console.log("aaaa")
    if(false){
        console.log(require("module1"))
    }
    console.log("bbbb")});Copy the code

Take a look at the requirejs source code:

Requirejs has two methods for obtaining dependencies. One is configuration, and the other is to use regex to match all require contents and then add dependencies. When the current module is called, the dependent module is checked to see if it is running.

cjsRequireRegExp = /[^.]\s*require\s*\(\s*["'] ([^ '"\s]+)["']\s*\)/g,
Copy the code

Modules that have been defined will be cached in an object with the name of the module as the unique key. If the cached module is called again, it does not need to be executed again.

Cache the results after execution

defined[id] = exports;
Copy the code

If the command is executed twice, check whether the command already exists. If yes, the command is not executed again.

function callGetModule(args) {
    //Skip modules already defined.
    if(! hasProp(defined, args[0])) { getModule(makeModuleMap(args[0], null,true)).init(args[1], args[2]); }}Copy the code

For remote dependencies, create a script, load the remote resource, and add the script to the header.

req.createNode = function (config, moduleName, url) {
    var node = config.xhtml ?
            document.createElementNS('http://www.w3.org/1999/xhtml'.'html:script') :
            document.createElement('script');
    node.type = config.scriptType || 'text/javascript';
    node.charset = 'utf-8';
    node.async = true;
    return node;
};
Copy the code

So what is UMD

When I first came across UMD, I was in the webPack package and wanted to build a library with several options, CommonJS, AMD, UMD. I was confused. What is UMD? Another module specification appeared without my knowledge, which made my head very big.

Gaze from Webpack:

output: {
    path: path.join(__dirname),
    filename: 'index.js',
    libraryTarget: "umd"// Here is the type of plug-in you want to package:"Swiper",}Copy the code

Take a look at the package:

!function(root,callback){
"object"==typeof exports&&"object"==typeof module? Module.exports =callback(require) {// nodejs module.exports=callback(require)"react"),require("prop-types"))
    :
    "function"==typeof define&&define.amd? // Determine whether requirejs AMD environment define("Swiper"["react"."prop-types"],callback)
        :"object"==typeof exports? Module.exports. Swiper exports.Swiper=callback(require()"react"),require("prop-types")) : root Swiper = callback (root. React, root PropTypes) / / global variable} (window, callback)Copy the code

Such a polyfill is instantly compatible with CommonJS, AMD and a global module. This is UMD, which is more of a compliant, polyfill, multi-module specification than a specification.

Where is the CMD?

For those of you with a keen eye, CMD is nowhere to be found, and the webpack does not have an option for the CMD module. CMD is a specification that takes the CommonJS specification and then ADAPTS it to support the browser side.

Let’s talk about the main differences between AMD and him:

The require keyword introduces the order of execution of the content. AMD is a concept that relies on pre-loading, whereas CMD is synchronous execution, executing the current module after encountering require.

define("c".function(require, exports, module) {
    console.log("bbb")}); define("b".function(require, exports, module) {
    console.log("aaa")
    require("c")
    console.log("ccc")}); seajs.use("b")
Copy the code

So it prints aaa, BBB, CCC. Execute in the order in which the code appears.

Of course this is the difference between synchronous code, as for asynchronous code, CMD and AMD are loaded from script, append to head, stored in module object, and then called according to id. But CMD is a little different, adding a little optimization:

if(! data.debug) { head.removeChild(node) }Copy the code

When the code is loaded and cached in the module, the script is removed from the head.

Afterword.

To borrow a word from Lu Xun, “there is no road in the world, but when more people walk, it becomes a road”. JS MODUDLE specification is also the same, use more people is the default solution.

I’ll leave the JS MODULE wars here, no one knows how long these MODULE specifications will survive, but the concepts are good. So learn the concept well, even if there is a new standard, and the old standard a contrast, find out the difference, to be analyzed, it will be easy to start!

Refer to the address

Do not forget to help the author of the cognitive module of the article, thank you guys:

  • Requirejs: The Requirejs website explains the history of AMD.
  • That bit of front-end modular development history: SeaJS ‘big man’s view of modules clears up my confusion with AMD
  • An explanation of AMD and Requirejs on Overflow

First nuggets ~ reproduced please note the source