ESM
ESM is the JS standard modularization specification introduced by ES6. Its design idea is as static as possible, so that the module dependencies and input and output variables can be determined at compile time.
Function: The function of the module consists of two commands: export and import. The export command is used to specify the external interface of a module, and the import command is used to input functions provided by other modules.
features
- Determine module dependencies and input and output variables at compile time
- Automatic adoption of strict mode
- A module is a file. All variables inside the module cannot be obtained externally
benefits
- Makes static analysis possible, such as type checking
- No longer need
UMD
Module format - In the future, the browser’s new apis will be available in module format and will no longer have to be global variables or
navigator
Object properties. - Objects are no longer required as namespaces (e.g
Math
Object), and in the future these functions could be provided through modules.
export
If you want outsiders to be able to read a variable inside a module, you must print that variable through the export keyword
- The output variable
// profile.js
export const a = 1;
export const b = 'aaa';
export const c = 2021;
// Another way to write it
const a = 1;
const b = 'aaa';
const c = 2021;
export {a, b, c}
Copy the code
The two notations above are equivalent, but the second is recommended because you can see at the end of the module what variables are being output
- Output function
export function fn() {
console.log()
}
// Another way to write it
function fn1(){}
function fn2() {}
export {fn1, fn2}
// Rename the function
export {fn1 as st1, fn2 as st2, fn2 as st3}
Copy the code
The above code renames the external interfaces of the functions v1 and v2 using the AS keyword. After the rename, V2 can be printed twice with different names.
- Note:
export
Commands specify the external interface of the module and must establish a one-to-one relationship with variables inside the module
For example, the following is an error
export 1; / / an error
const a = 1;
export a; / / an error
Copy the code
Both of the above methods give an error because there is no external interface provided. The first way to write it is to print 1 directly, and the second way to write it is to print m directly, again. 1 is just a value, not an interface.
The correct way to write it
/ / write 1
export const a = 1;
/ / write 2
const a = 1;
export { a }
/ / writing 3
const a = 1;
export {a as m}
Copy the code
The above three notations are correct, specifying the external interface A. Other scripts can use this interface to get the value 1. Their essence is to establish a one-to-one correspondence between the interface name and the module’s internal variables.
Functions and classes must also follow the above rules
function fn() {}
export fn; / / an error
export function fn() {} / / right
function fn() {}
export {fn} / / right
Copy the code
export
The interface of the statement output is dynamically bound to its corresponding value, that is, the real-time value of the module is obtained through the interface
export let foo = 'bar';
setTimeout(() = > foo = 'baz'.500);
Copy the code
The above code outputs as bar and baz after 500ms
-
Export can only appear at the top level of a module, not in a block-level scope
-
Export Default: used to export modules by default. Only one export default can exist in a module
// index.js
export default function() {... }// The anonymous function can be given any name
import aaa from './index.js'
Copy the code
import
The import command is used to input functions provided by other modules
import { a, b, c } from './index.js';
// Use it directly
console.log(a);
console.log(b);
console.log(c);
Copy the code
The import command can also rename loaded modules
import { a as st1, b as st2, c as st3 } from './index.js';
Copy the code
import
The variables in the command input are read-only because they are essentially input interfaces, that is, interfaces are not allowed to be overwritten in scripts that load modules
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
Copy the code
In the above code, the script loads variable A and reassigns it to an error because A is a read-only interface. However, if A is an object, overwriting a’s properties is allowed.
import { a } from './xxx.js'
a.foo = 'hello'; // It is valid
Copy the code
-
The from after import specifies the location of the module file, which can be a relative or absolute path. If you don’t have a path but just a module name, you must have a configuration file that tells the JavaScript engine where the module is.
-
The import command is promoted to the top of the module and executed first.
-
Because import is executed statically, you cannot use expressions and variables, which are syntactic structures that are only available at run time.
/ / an error
import { 'f' + 'oo' } from 'my_module';
/ / an error
let module = 'my_module';
import { foo } from module;
/ / an error
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
Copy the code
import
Statement in nofrom
If the import of the same module is executed multiple times, it is executed only once
import 'lodash';
import 'lodash';
Copy the code
- If the import statement is executed for the same module, it is equivalent to loading it only once
import { foo } from 'my_module';
import { bar } from 'my_module'; // This is not recommended
/ / is equivalent to
import { foo, bar } from 'my_module';
Copy the code
Composite writing
If the same module is input and then output within a module, the import statement can be written together with the export statement.
export { foo, bar } from 'my_module';
// It can be used as an example
import { foo, bar } from 'my_module';
export { foo, bar };
Copy the code
import()
The ES2020 proposal introduces an import() function that supports dynamic loading of modules and returns a Promise object.
import(module)
Copy the code
And CommonJs
- The CommonJS module prints a copy of the value, the ESM module prints a reference to the value.
- The CommonJS module is run time loaded and the ESM module is compile time output interface.
- CommonJS module
require()
Synchronous loading module, ES6 moduleimport
Commands are loaded asynchronously, with a separate module-dependent parsing phase.
CommonJS modules can only determine these things at run time.
/ / CommonJS module
let { stat, exists, readfile } = require('fs');
/ / is equivalent to
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
Copy the code
The above code essentially loads the FS module as a whole, generates one object, and then reads three methods from those three objects. This loading is called runtime loading, because the object is only available at runtime, making it completely impossible to do “static optimization” at compile time.
NodeJs
The ESM module is supported from version 13.2
CommonJS
Module Loads the ESM module
CommonJs cannot load ESM modules through require(), only through import()
(
async() = > {await import(modlue)
}
)()
Copy the code
One reason require() does not support the ESM module is that it is loaded synchronously, whereas ES6 modules can use top-level await commands internally and thus cannot be loaded synchronously.
The ESM module is loadedCommonjs
The IMPORT command for ESM modules can load CommonJs modules, but only as a whole, not as a single output item