A, modules,

1.1 What is a module

  1. Encapsulate a complex program into several blocks (files) according to certain rules (specifications) and combine them together
  2. The internal data and implementation of the block isprivateOnly expose interfaces (methods) to communicate with other external modules

1.2 Why modularity

  1. Can cause naming conflicts and global contamination.
  2. Too many JS files on the same page can cause page blocking and HTTP requests.

Early modularity is achieved through closures to privatize and modularize variables.

ModuleA = function () {var a,b; return { add: function (c){ return a + b + c; }; }} ()Copy the code

Second, the CommonJS

2.1 Basic Concepts

The CommonJS specification states that within each module, the module variable represents the current module (a JS file is a module). This variable is an object whose exports property (module.exports) is the interface to the outside world. Loading a module loads the module.exports property of that module.

Each file is a module with its own scope. Variables, functions, and classes defined in one file are private and invisible to other files. On the server side, modules are loaded synchronously at runtime. On the browser side, modules need to be compiled and packaged in advance. The CommonJS specification loads modules synchronously, meaning that subsequent operations cannot be performed until the load is complete.

Basic syntax:

  • Exposure module:module.exports = valueexports.xxx = value
  • Introduction module:require(xxx)If it isThird-party modules, XXXModule name; If it isCustom modules, XXXModule file path
var a = 1; var b = function (){} module.exports.a = a; module.exports.b = b; Var main = require('./main') main.a main.bCopy the code

Webpack is often used in configuration. Webpack runs in the Node environment and uses the CommonJS specification.

2.2 the characteristics of

  • All modules run in the module scope and do not pollute the world
  • A module runs multiple times, executes once, and then caches it. To get the module to re-execute, you have to clear the cache
  • He does it in the order of introduction, which is synchronous execution

Browser-side modules, instead of synchronous loading, can only be asynchronous loading, which is where the AMD specification was born.

Third, AMD

3.1 Basic Concepts

Asynchronous loading module, allow to specify the callback function, browser side generally using AMD specifications

The require.js AMD specification specifies that all modules and dependencies are loaded asynchronously, so that js files are not imported at once.

Define (function(){return module}) define(['module1', 'module2'], function(m1, M2){return module}) // Introduce module require(['module1', 'module2'], function(m1, m2){// use m1/m2})Copy the code

3.2 the characteristics of

  1. According to the need to loadThat is, you load the module by introducing it, not by loading it all at once on the page
  2. Asynchronous loadingAll loads are asynchronous and do not block the page

Third, CMD

Specifically used for the browser side, the module load is asynchronous, the module will be loaded and executed when it is used

Sea.js

// define(function(require, exports,) Module){exports. XXX = value module. Exports = value}) define(function(require, exports, Var module2 = require('./module2') // Require. Async ('./module3', Var m1 = require('./module1') var define(function (require) {var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show() })Copy the code

Fourth, AMD and CMD differences

AMD (e.g. Require.js) To promoteDependencies are front-loaded and executed ahead of time, and declare dependencies at the front,

In all dependencies areloadingperformThe completion ofThen the master logic is executed
Fast and wasteful of resources Require, require, require, require
CMD (e.g. Sea-.js) To promoteRely on nearby, which dependencies need to be resolved,

In all dependenciesTo loadThe dependency is executed when the require statement is encountered
Resource saving and poor performance No global require

The biggest difference between AMD and CMD is that the execution time of dependent modules is different, rather than the loading time or way is different, both are asynchronous loading modules. AMD dependency front, JS can easily know who the dependency module is, immediately load. CMD relies on modules that need to be parsed into strings. This is also one of the many complaints about CMD, sacrificing performance for ease of development. In fact, parsing modules takes a negligible amount of time. In a word: both load asynchronously, but at different times. AMD relies on forward execution, CMD relies on close execution, delayed execution.

Five, the UMD

UMD is a combination 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.

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

6. ES6 modularity

The ES6 module is designed to be as static as possible, so that the module dependencies, as well as the input and output variables, can be determined at compile time. Both CommonJS and AMD modules can only determine these things at runtime. For example, a CommonJS module is an object, and you have to look for object properties when you enter it. The ES6 Module is not currently supported by the browser by default, so it needs to use Babel, which often throws errors when writing daily demos.

ES6 uses the keyword import to import modules, and the keyword export to export modules:

/** / var a = 0; export { a }; // export const b = 1; // let c = 2; Export default {c}// let d = 2; Export default {d as e}// import {a} from './a.js' // The.js suffix can be omitted import main from './c' // For export default, use main.c import 'lodash' // just execute the lodash module without entering any valuesCopy the code

7. Differences between ES6 module and CommonJS module

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

Once a value is output, changes within the module do not affect that value. Also, no matter how many times the CommonJS module is loaded, it will only run once on the first load, and any subsequent load will return a cache of the results of the first run, unless the system cache is manually cleared. When the JS engine statically analyzes the script, it will generate a read-only reference when it encounters the module loading command import. When the script is actually executed, it will value the loaded module according to this 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.

  1. The CommonJS module is run time loaded, and the ES6 module is compile time output interface

CommonJ loads an object (that is, the module.exports property) that is generated only after the script runs. That is, the entire module is loaded on input, an object is generated, and methods are read from that object. This type of loading is called runtime loading.

// CommonJS module let {stat, exists, readFile} = require('fs'); // equivalent to let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;Copy the code

An ES6 module is not an object, and its external interface is a static definition that is generated during the code static parsing phase. The export command explicitly specifies the output code, and the import command takes the form of a static command. 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 or static loading.

// ES6 module import {stat, exists, readFile} from 'fs';Copy the code

Eight, summary

  1. CommonJSThe specification is mainly used forServer-side programming, the loading module issynchronousThis is not suitable in the browser environment, because synchronization means blocking loading, browser resources are loaded asynchronously, hence the AMD, CMD solution.
  2. AMDSpecification inBrowser environmentIn theAsynchronous loading moduleAnd it can be parallelLoading multiple modules. However, AMD specifications are expensive to develop, code is difficult to read and write, and semantics are not smooth in the way modules are defined.
  3. CMDThe specification is similar to the AMD specification in that both are used forBrowser programming.Rely on proximity and delay execution, can be easily inNode.jsIn the running. However, depending on SPM packaging, the loading logic of modules is biased.
  4. ES6In the language standard level, the module function is realized, and the implementation is quite simple, can completely replace CommonJS and AMD specifications, become a common browser and server module solution.

Refer to the article

  1. Front-end Modular Details (Full version)
  2. 【JS basics 】 Understand the front-end modular specification
  3. The evolution of the front-end JavaScript modular specification
  4. Front-end science series -CommonJS: Not front-end revolution front-end – details, wait to see!!