As the front-end engineering more and more complex, the project is more and more big, modern front-end development all the time and deal with all sorts of module, at the beginning of the program design, can according to different function code will be split into different segments, each segment to realize their specific mission, finally through the interface will be scattered fragments together, and also is the so-called modular development. To put it simply, a module is a file that realizes a specific function, such as introducing a tripartite package into the project or providing a JS tool function file for a function alone. These can be called modules.

Why modular development

In early JavaScript, there was no concept of module. Faced with multiple JS files, only the <script> tag could be inserted into HTML one by one, which led to the need to ensure the introduction order if there was a dependency between JS files. At the same time, there was the risk of variable naming conflict. Every JS file needs to send a request to the server, which is a disaster for page load performance.

In order to solve many problems under the non-module development, since 2009, In the JS community, AMD specification (Asynchromous Module Definition) and CMD specification (Common Module) represented by RequireJS and SeaJS have emerged successively Definition), and the CommonJS specification for NodeJS’s implementation.

CommonJS

Import and export

CommonJS specifies that each file is an independent module, each module does not affect each other, each module has an independent scope. Import modules using require and export modules using module.exports or exports.

// A.js
/ / module exports export
module.exports = {
    test() {
        console.log('Export module method 1')}}/ / exports export
exports.test = function() {
    console.log('Export module mode 2')}// B.js
let a = require('./A.js)
a.test()
Copy the code

The two ways of deriving are equivalent. Module. exports is an empty object and exports are stored inside module.exports, which points to Module. exports. Exports cannot be reassigned, otherwise the direction of exports will change and exports will fail.

ES Module

In 2015, ECMAScript6.0 formally defined the JS module standard, making JS officially equipped with the module feature. ES Module also regards each file as a Module, and each Module has its own scope. Import is used for Module import and export is used for export.

Import and export

// A.js
// Plain export
export function bar () {
    console.log('ES Module')}// Export by default
let def = 'ES Module'
export default def

// B.js
/ / import
import { bar } from './A.js'
bar()

// Import the default export
import a from './A.js'
console.log(a)

// Batch import
import * as c from './A.js'
Copy the code

CommonJS and ES Module

For ordinary import and export should be modern front-end development is easy to do, and no one will ask how to import and export modules in the interview, so we still need to pay attention to their differences

Module processing

In terms of Module processing, the relationship between Module dependencies in CommonJS takes place during code runtime, whereas ES Module takes place during code compilation. In CommonJS, when module A loads module B, the code in module B will be executed. Expressions are supported by the module path imported by require. In addition, if can be used to determine whether to load A module, so the CommonJS module cannot clarify the relationship between dependencies before being executed.

// A.js 
module.exports = {
    test: 'test'
}

// B.js
let path = 'A.js'
let test 
if (true) {
    test = require('/' + path)
}
console.log(test)
Copy the code

In ES Module, the dependency between modules can be analyzed in the compilation stage. The path that does not support import is an expression, and the export statement must be written in the top-level area of the Module.

Differences in derived values

In ES Module, the imported value is A reference to the exported value of the original Module. It can be verified by the following example that when the value of num in the original Module A is changed through the add method, the value of num in Module B changes with the change of the value of num in Module A.

// A.js
let num = 1
function add () {
    num ++
    console.log(The value of num in module A: + num)
}
export {
    num,
    add
}

// B.js
import { num, add } from "./A.js";
console.log('num =' + num)
add()
console.log('Value of num after calling add :' + num)

// The value of num is 1
// The value of num in module A is 2
// num = 2 after the add method is called
Copy the code

In CommonJS, the imported value is A copy of the exported value of the original module. The value of num in module B does not change with the change of the median value in module A.

// A.js
let num = 1
function add () {
    num ++
    console.log(The value of num in module A: + num)
}
module.exports = {
    num,
    add
}

// B.js
let obj = require('./A.js')
console.log('num =' + obj.num)
obj.add()
console.log('Value of num after calling add :' + obj.num)

// The value of num is 1
// The value of num in module A is 2
Num = 1 after the add method is called

Copy the code

conclusion

ES Module, as the official JS Module standard, is also a clear direction of JS modular development, and the community standard CommonJS standard is also popular among NodeJS, the top practitioners, but currently NodeJS is supporting the modular implementation of ES Module. You can import and export ES Modules by setting “type”: “module” in package.json or changing the file suffix to. MJS