First, the concept of modularity

Modularization is refers to the top-down (function) the problem of a complex process of divided into several modules, is refers to by some rules in the programming of program (code) segmentation, tissue, packaging, each module to complete a specific function, then put all of the modules assembled according to certain rules, merged into a whole, finishing the all function of the whole system

From node.js-based commonJS server modular, to front-end browser-based AMD, CMD modular, and then to ECMAScript2015 started native built-in modular, JavaScript modular solutions and systems are increasingly mature.

TypeScript also supports modularity and predates the standardization of the ECMAScript module system, so there is support for the ECMAScript module system in TypeScript as well as some features of its own

Two, modular process

  • CommonJS
  • AMD
  • UMD
  • ESM

Regardless of the modularity specification, the focus is on maintaining module independence while interacting well with other modules

  • How to define a module and its internal private scope
  • How to export the internal data of a module
  • How to import data from other external modules

CommonJS: Modular based on server and desktop

In the early days, the need for modularity was not so strong for JavaScript code running in the browser, but rather for server-side and desktop applications (where the code and requirements for server-side and desktop applications are more complex). The CommonJS specification is a server-side modularity specification that provides solutions and standards for non-browser-based modularity implementations. NodeJS uses this specification.

1. Independent module scope

A file is a module and has its own scope

2. Export internal data of the module

Exports internal module data through module.exports or exports objects

// a.js
let a = 1;
let b = 2;

module.exports = {
  x: a,
  y: b
}
// or
exports.x = a;
exports.y = b;
Copy the code

3. Import external module data

Import external module data via the require function

// b.js
let a = require('./a');
a.x;
a.y;
Copy the code

Four, AMD: browser-based modular

AMD: Because CommonJS specification has some features (file system based, synchronous loading), it does not apply to the browser side, so it defines a separate specification for the browser side

AMD(Asynchronous Module Definition)

Github.com/amdjs/amdjs…

Browsers do not have the code to implement the specification, which can be addressed through some third-party libraries

1.requireJS

Liverpoolfc.tv: requirejs.org/

(1) the HTML

Js file and set the entry file through data-main

// 1.html
<script data-main="js/a" src="https://cdn.bootcss.com/require.js/2.3.6/require.min.js"></script>
Copy the code
(2) Independent module scope

A module is defined through a define method that simulates the module-independent scope within the method. A file can have multiple define methods, but it is recommended to set only one define method for a file.

// b.js
define(function() {
  // Module internal code
})
Copy the code
(3) Export the internal data of the module

Export internal module data by using return

// b.js
define(function() {
  let a = 1;
	let b = 2;
  return {
    x: a,
  	y: b
  }
})
Copy the code
(4) Import external module data

Import external module data through the pre-dependency list

// a.js
// Define a module and import the./b module
define(['./b'].function(b) {
	console.log(b);
})
Copy the code

2.requireJSCommonJSstyle

Require.js also supports commonJs-style syntax

(1)Example Export internal data of a module
// b.js
define(function(require.exports.module) {
  let a = 1;
	let b = 2;
  module.exports = {
    x: a,
    y: b
  }
})
Copy the code
(2) Import external module data
// a.js
define(function(require.exports.module) {
  let b = require('./b')
  console.log(b);
})
Copy the code

UMD: multiterminal isomorphism

Strictly speaking, UMD is not a set of module specifications. It is mainly used to deal with the differences between CommonJS, AMD and CMD, so that the module code can work in different module environments. With the popularity of Node.js, both the front end and the back end can be developed in JavaScript, which makes it more or less possible for the front and back ends to use the same code, especially low-level code that doesn’t depend on the host environment (browser, server). We can achieve a set of code multi-application (isomorphism), where the use of different modular standards is also a problem to be solved, UMD is a solution

// Encapsulate logic
(function(root, factory){Determine the environment}(parameters1: Operating environment and parameters2: factory function))Copy the code
// Encapsulate the UMD

(function (root, factory) {
  	if (typeof module= = ="object" && typeof module.exports === "object") {
        // Node, CommonJS environment
        module.exports = factory();
    }
    else if (typeof define === "function" && define.amd) {
      	// In AMD module environment
        define(factory);
    } else {
      	// Do not use any module system, directly mount to the global
      	root.kkk = factory();  // KKK is custom, root is passed in this, representing the runtime environment
    }
}(this.function () {
    let a = 1;
		let b = 2;

    // The module exports data
    return {
        x: a,
        y: b
    }
}));
Copy the code

ESM: Modular world of one

Since ECMAScript2015 / ECMAScript6 JavaScript native module is introduced, and now the mainstream browsers also has the very good support, at the same time in the Node. Js also have the support, So in the future, javascripts based programs will gradually be unified in both front-end browsers and back-end Node.js.

1. Independent module scope

A file is a module, has its own scope, and exported modules are automatically in strict mode, i.e. : ‘use strict’, which must be declared before assigning values.

The script tag needs to declare type=”module”

2.Example Export internal data of a module

Use the export statement to export data inside the module

// Export a single feature
export letName1 name2,... , nameN;export letName1 =... , name2 =... ,... , nameN;export function FunctionName(){... }export class ClassName {... }// Export the list
export { name1, name2, …, nameN };

// Rename the export
export { variable1 as name1, variable2 asName2,... , nameN };// Export by default
export default expression;
export default function (...) {... }export default function name1(...) {... }export { name1 as default,... };// The module redirects the export
export * from... ;export { name1, name2, …, nameN } from... ;export { import1 as name1, import2 asName2,... , nameN }from... ;export { default } from... ;Copy the code

3. Import external module data

Imports fall into two modes

  • Static imports
  • Dynamic import
(1) Static import

Importing modules using import statements is called static import

Static imports do not support lazy loading and must be at the beginning of the module

import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { foo , bar } from "module-name/path/to/specific/un-exported/file";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export[, [...]]}from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
Copy the code
document.onclick = function () {

    // Import must be placed at the beginning of the current module load
    // import m from './m.js'

    // console.log(m);

}
Copy the code
(2) Dynamic import

In addition, there is a function-like dynamic import() that does not rely on the script tag of type=”module”.

The keyword import can be used to dynamically import modules as if they were functions. Called this way, a Promise is returned

import('./m.js')
  .then(m= > {
    / /...
});
// Also support await
let m = await import('./m.js');
Copy the code

The data returned by the import() method is wrapped in an object, even for default