Front-end modularization
Why is that?
- Modern Web sites are evolving into APPS
- Code complexity is increasing
- Projects are getting bigger and bigger
- Code deployment needs to be optimized through subcontracting
- Code reuse requirements
- .
At present, the Web side of the mainstream modular standard
- CommonJS
- AMD
- CMD
- UMD
- ES6
CommonJS
background
The creators of CommonJS originally planned to create a modular standard for the Javascript language, independent of any browser environment, and then use the standard to force browser makers to modify their implementations to support the standard. However, the creators ignored some factors that browsers cannot change. Such as network issues and single-thread blocking issues, and there is no way for browsers to provide the four CommonJS variables module. Exports, exports, glabal and require, so currently CommonJS is mainly used in Nodejs.
use
- Each file is a module, and each module has its own scope. All internal variables and functions are invisible to other modules
- Modules can be exported through module.exports or exports, where module represents the current module
- You can import it in a separate file via require
- Each module can be loaded multiple times but is only run on the first load and then cached for subsequent loads
- Load synchronously in the order in which the code appears
export
module.exports.TestModule = function() {
console.log('exports');
}
Copy the code
or
exports.TestModule = function() {
console.log('exports');
}
Copy the code
Exports is a reference to module.exports. If exports is called before exports is called, then exports is called. Exports =module.exports; exports=module.exports; exports=module.
The import
const mymodule = require('./MyModule'); // If there is no suffix, the completion lookup will be performed automatically in the order of.js,.json, and.nodeCopy the code
The loading process
- Loading from cache is preferred
- If it is not in the cache, check if it is a core module, if it is loaded directly
- If it is not a core module, check whether it is a file module, parse the path, locate the file based on the resolved path, and then execute and load it
- If none of the above, recurse up the current path to the node_modules directory of the root directory
Loop dependent processing
CommonJS each file is a module that is executed when it is first loaded, and only the parts that have already been executed and exported are loaded when a cyclic dependency is encountered. reference
AMD(Asynchronous Module Definition)/RequireJS
background
AMD’s original intention is to solve the following problems existing on the browser side:
- Numerous
- You need to manually control the loading sequence
- CommonJS has some problems, such as one module per file, browser unfriendly, etc
use
The basic grammar
define(id? , dependencies? , factory);Copy the code
Dependencies are an array of dependencies (including a path and an ID) and a callback function that executes automatically when all dependencies are loaded.
If it depends on ‘require’, ‘exports’ or’ module ‘, it is resolved as a free variable according to CommonJS documentation. If there are no dependencies, it is passed [“require”, “exports”, “module”] by default. But it also depends on the number of arguments in the factory function.
Define the way
- Define a module with id “alpha” using require, exports
define("alpha"["require"."exports"."beta"].function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
return require("beta").verb(); }});Copy the code
- Anonymous module
define(["alpha"].function (alpha) {
return {
verb: function() {returnalpha.verb() + 2; }}; });Copy the code
- Modules without dependencies
define({
add: function(x, y){
returnx + y; }});Copy the code
- By wrapping modules defined by CommonJS
define(function (require, exports, module) {
var a = require('a'),
b = require('b');
exports.action = function () {};
});
Copy the code
This definition will be AMD loader by the Function. The prototype. The toString () (not all browsers support) into the form below:
define(['require', a', 'b'], function (require) { var a = require('a'), b = require('b'); exports.action = function () {}; });Copy the code
Project currently in use
- jQuery1.7
- Dojo1.7
- EmbedJS
- .
CMD(Common Module Definition)/Seajs
Different from AMD’s dependency front, CMD advocates dependency nearby, CMD has a detailed Chinese reference document, no further details.
UMD mode (Universal Module Definition)
UMD is designed to solve scenarios where multiple package loaders (such as AMD and CommonJS) are needed at the same time. For example, the UMD consists of two parts:
- A just-in-time function to check supported module loaders that takes two arguments, the first a reference to the global scope and the second our module-defined function
- A module defines a function that takes as the second argument to a just-in-time function that takes any number of arguments based on the number of dependencies.
Examples (AMD and CommonJS support)
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports'.'b'], factory);
} else if (typeof exports === 'object'&& typeof exports.nodeName ! = ='string') {
// CommonJS
factory(exports, require('b'));
} else {
// Browser globals
factory((root.commonJsStrict = {}), root.b);
}
}(this, function (exports, b) {
exports.action = function () {};
}));
Copy the code
So UMD can theoretically support a wide variety of module loaders
ES6 module
background
Implementing module functionality from the language standard level can replace AMD and CommonJS as a common solution for the front and back ends.
Design idea
For both CommonJS and AMD, dependencies are determined at runtime, i.e. loaded at runtime. CommonJS loads copies, while ES6 Modules load dependencies at compile time. All dependencies are actually loaded as references.
export
Methods a
export var first = 'test';
export function func() {
return true;
}
Copy the code
Way 2
var first = 'test';
var second = 'test';
function func() {
return true;
}
export {first, second, func};
Copy the code
The as keyword
var first = 'test';
export {first as second};
Copy the code
The AS keyword can rename exposed variables or methods, and the same variable can be exposed multiple times after being renamed.
export default
Export default exports the default output, that is, you do not need to know the name of the output in the module. You can specify any name for the output when importing it.
/ / exportexport default function () {
console.log('foo'); } // Import import customName from'./export-default'; / / errorexport default var a = 1; //exportDefault exports a variable named default, so it cannot be followed by a statementCopy the code
Importing a default module does not require curly braces, and the exported default variable or method can have a name, but is invalid externally. Export default can be used only once.
pit
Export requires that the interface exposed must correspond to the internal variables of the module one by one, but cannot directly output values. This can be understood in combination with the previous statement that all imports are references.
/ / an errorexport1; Var m = 1;exportm; / / an errorfunction f() {}
exportf; / / rightexportvar m = 1; Var m = 1;export{m}; Var n = 1;export{n as m}; / / rightexport function f() {}; / / rightfunction f() {}
export {f};
Copy the code
The import
The normal import
import {firstName, lastName, year} from './profile';
Copy the code
Import module location can be relative path or absolute path,.js can be omitted, if there is no path but the module name, you need to tell the engine through the configuration file to find the location.
The as keyword
import { lastName as surname } from './profile';
Copy the code
The import command is promoted to the head of the module, so the location of the write is not as important, but expressions and variables cannot be used to import.
Load the entire module (no output)
import 'lodash'; // It is only loaded and cannot be usedCopy the code
Load the entire module (with output)
import * as circle from './circle';
console.log('Circle area:' + circle.area(4));
console.log('Circumference:' + circle.circumference(14));
Copy the code
Import * ignores the default output
Import/export composite usage
First in, then out
export { foo, bar } from 'my_module'; // Equivalent to import {foo, bar} from'my_module';
export { foo, boo};
Copy the code
Overall import and output and default
// Total outputexport * from 'my_module'; // Export default, as mentioned earlier,exportDefault actually exports the default variableexport { default } from 'foo'; // Change the named interface to defaultexport { es6 as default } from './someModule';
Copy the code
Module inheritance
export * from 'circle';
exportVar e = 2.71828182846;export default function(x) {
return Math.exp(x);
}
Copy the code
Export * ignores default.
The main points of
- The ES6 module defaults to strict mode
- One file per module
- The import of ES6 can be anywhere in the module, but it must be at the top level; an error will be reported if it is in the block-level scope
- The export command specifies the external interface and must establish a one-to-one relationship with variables inside the module
- The interface output by the export statement is dynamically bound to its corresponding value, that is, the real-time value inside the module can be obtained through the interface
The browser uses ES6 modules
<script type="module" src="foo.js"></script>
Copy the code
For <script> of type=”module”, the browser performs asynchronous loading without blocking the browser.
summary
Standards/Features | Applicable scenario | Synchronous/asynchronous | Module dependencies determine when |
---|---|---|---|
CommonJS | The service side | synchronous | The runtime |
AMD | The browser | asynchronous | The runtime |
CMD | The browser | Synchronous or asynchronous | The runtime |
UMD | Server side/browser side | Synchronous or asynchronous | The runtime |
ES6 Module | Server side/browser side | Synchronous or asynchronous | Compile time |