Today, due to the large size of the echarts files introduced in the project, requireJS often timed out and had to load echarts diagrams separately. However, an AMD-compliant module generated using echarts’s own online build tool reported an error, so it had to be loaded using Echarts’s global function using requireJS shim. Take this opportunity to learn about AMD, CMD, CommonJS and UMD specifications and the differences between them.

Javascript modular

Before we look at these specifications, let’s look at what modularity is.

Modularization refers to the systematic decomposition of a complex problem or a series of mixed problems in accordance with a categorical thinking. Modularity is a way of dealing with the decomposition of complex systems into manageable modules with a more rational code structure and higher maintainability. Can imagine a huge system code, by integration and optimization divided into logical modules, is a kind of significance for the existence of software. For the software industry: decoupling the complexity of software systems makes it possible to manage, develop, and maintain systems no matter how large they are.

There are some technical definitions of modularity: modularity is the property of a software system that is decomposed into a set of highly cohesive, low-coupling modules. Ideally, we only need to complete some of our core business logic code, and other dependencies can be used by directly loading modules that have been written by others.

First, since it is modular design, the capabilities required to be a modular system:

  1. Define encapsulated modules.

  2. Define the dependencies of the new module on other modules.

  3. Support can be introduced for other modules.

Ok, so there has to be something to establish a modular specification, otherwise the various module loading methods will only muddle the board further. So in JavaScript, there are some non-traditional Module development methods specification CommonJS Module specification, AMD (Asynchronous Module Definition), CMD (Common Module Definition), etc.

CommonJS

CommonJS is the specification for server-side modules, which Is adopted by Node.js.

According to the CommonJS specification, a single file is a module. The load module uses the require method, which reads a file and executes, finally returning the exports object inside the file.

Such as:

// foobar.js // var test = 123; Function foobar () {this.foo = function () {// do someing... } this.bar = function () { //do someing ... } //exports objects are public var foobar = new foobar(); exports.foobar = foobar;Copy the code
Var test = require('./boobar').foobar; test.bar();Copy the code

CommonJS loads modules synchronously, so you can’t perform any operations until the load is complete. For example, Node.js is mainly used for server programming, and the loaded module files are generally stored in the local hard disk, so the loading is relatively fast, without considering the asynchronous loading mode, so the CommonJS specification is more suitable. However, in a browser environment, to load modules from the server, this must be done in asynchronous mode. Hence the AMD CMD solution.

AMD and RequireJS

AMD

AMD stands for “Asynchronous Module Definition”.

AMD designed a concise write module API: DEFINE (ID? , dependencies? , factory); The first parameter ID is a string that represents the module id and is optional. If not, the module id should be defined by default as the id of the requested script in the loader. If present, the module id must be top-level or an absolute id. The second parameter, dependencies, is an array literal that identifies the modules that the current module depends on. The third argument, factory, is a function or object that needs to be instantiated.

By permutations and combinations of parameters, this simple API can handle a wide variety of application scenarios, as described below.

  • Define a dependency free module

  • define( { add : function( x, y ){ return x + y ; }});Copy the code
  • Define modules with dependencies

  • define(["alpha"], function( alpha ){ return { verb : function(){ return alpha.verb() + 1 ; }}});Copy the code
  • Define the data object module

  • define({
        users: [],
        members: []
    });Copy the code
  • A named module

  • define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){ export.verb = function(){ return beta.verb(); // or: return require("beta").verb(); }});Copy the code
  • Packing module

  • define(function(require, exports, module) { var a = require('a'), b = require('b'); exports.action = function() {}; });Copy the code

    Regardless of the extra layer of functions, the format is the same as Node.js: use require to get dependent modules, use exports API.

    In addition to define, AMD also retains the keyword require. Require is a global identifier reserved for the specification and may or may not be implemented as a Module loader.

    Module is loaded

    require([module], callback)

    The AMD modular specification uses the global or local require function to load one or more modules, and the callback function after all modules are loaded.

    Among them:

    [module] : is an array whose members are the modules to load; Callback: is a callback function after the module has finished loading.

    For example, load a Math module and call the math.add(2, 3) method;

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

    RequireJS

    RequireJS is a front-end modular management library that follows the AMD specification and was written by James Burke, the founder of the AMD specification. So it’s no exaggeration to say that RequireJS is an ELABORATION of the AMD specification.

    RequireJS basic idea is: through a function to all the needed or rely on module implements load to come in, and then return a new function (module), all of our business code of new module within the function operation, its internal also can use unlimited since already loaded in the module.

    Copy the code

    The main.js file under scripts is the specified main code script file from which all dependent module code files will be asynchronously loaded into execution.

    Define is used to define modules, and RequireJS requires each module to be in a separate file. It can be divided into independent modules and non-independent modules according to whether they depend on other modules.

    define({
        method1: function(){},
        method2: function(){}
    });Copy the code

    Is equivalent to the

    define(function() {
        return {
            method1: function(){},
            method2: function(){}
        }
    });Copy the code
  • An independent module that has dependencies on other modules.

  • define([ 'module1', 'module2' ], function(m1, m2) {
        ...
    });Copy the code

    Or:

    define(function(require) { var m1 = require('module1'), m2 = require('module2'); . });Copy the code

    Taking a look at the RequireJS implementation, its require implementation simply extracts the module name after require and puts it into a dependency.

  • The require method calls the module

  • When require calls the module, its parameters are similar to define.

    require(['foo', 'bar'], function(foo, bar) { foo.func(); bar.func(); });Copy the code

    The callback function is executed after the foo and bar modules are loaded.

    You can also call the module require from within the define definition module, as in the previous example

    define(function(require) { var m1 = require( 'module1' ), m2 = require( 'module2' ); . });Copy the code

    Define and require these two modules, call module method together called AMD mode, define module clear, will not pollute global variables, clear display dependencies. AMD mode can be used in a browser environment and allows modules to be loaded asynchronously or dynamically on demand.

    Website (www.requirejs.org/) API (www.requirejs.org/docs/api.ht…

    CMD and SeaJS

    CMD is the normalized output of SeaJS module definitions during the roll-out process

    • For dependent modules AMD is executed early, CMD is executed late. Since 2.0, however, RequireJS has also been deferred (or rejected, depending on how it is written).

    • CMD advocates dependency nearby, AMD advocates dependency front.

    / / AMD define (['. / a ', '/' b], function (a, b) {/ / rely on the start write a.t est (); b.test(); }); //CMD define(function (exports, requie, module) {var a = require('./a'); a.test(); . If (status) {var b = './b'; b.test(); }});Copy the code

    Although AMD also supports CMD, dependency prefixes are the default module definition for official documentation.

    • The DEFAULT AMD API is one when multiple use, CMD strict distinction advocates a single responsibility. For example, in AMD require is divided into global and local. There is no global require in CMD. Seajs.use () is provided to enable the module system to load and start. Every API in CMD is simple and pure.

    UMD

    UMD is a mashup of AMD and CommonJS

    AMD modules evolve on a browser-first basis, loading modules asynchronously. The CommonJS module follows the server first principle of synchronous loading and does not require unwrapped modules. This forced people to come up with another, more generic pattern, UMD (Universal Module Definition). Looking for a cross-platform solution.

    UMD determines whether any module (exports) that supports Node.js exists and uses node.js module mode if it does. Check whether AMD is supported (define exists). If AMD exists, load modules in AMD mode.

    (function (window, factory) {
        if (typeof exports === 'object') {
         
            module.exports = factory();
        } else if (typeof define === 'function' && define.amd) {
         
            define(factory);
        } else {
         
            window.eventUtil = factory();
        }
    })(this, function () {
        //module ...
    });Copy the code