What’s the difference between CommonJS and ES6 modules?

The CommonJS module outputs a copy of a value. ES6 module outputs a reference to a value

Commonjs usage, let’s take a look

1. Create a lib.js file first

// lib.js
const counter = 3;
const incCounter = () = >{
  counter++
}

module.exports = {
  counter,
  incCounter
}

Copy the code

2. Create a main.js file and import it using commonjs

// main.js
var lib = require('./lib');
console.log(lib)
console.log(lib.counter);  / / 3
lib.incCounter();
console.log(lib.counter); / / 3
Copy the code

After the lib.js module is loaded, its internal changes do not affect the output lib.counter. This is because mod.counter is a primitive value and will be cached;

Esmodule usage, let’s take a look

// lib.js
export let counter = 3;
export function incCounter () {
  counter++;
}
Copy the code
// main.js
import { counter, incCounter } from './util.mjs'

console.log(counter);  / / 3
incCounter()
console.log(counter)  / / 4

Copy the code

ES6 modules do not cache run results, but dynamically remove loaded module values, and variables are always bound to the module in which they reside.

Note: Variables imported via esModule cannot be changed by reassignment.

The CommonJS module is loaded at runtime, while the ES6 module is output at compile 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 (that is, all the methods that load FS), generates an object (_fs), and then reads three methods from that object. This type of loading is called “runtime loading” because the object is only available at runtime, making it completely impossible to do “static optimization” at compile time. So commonJS is a run-time mode of loading modules.

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

The essence of the above code is to load three methods from the FS module and none of the others. This type of loading is called “compile time loading” or static loading. ES6 modules can be loaded at compile time, which is more efficient than CommonJS modules.

The CommonJS module require() is loaded synchronously, ES6 module import command is loaded asynchronously, there is a separate module dependent parsing phase

Synchronous loading: Synchronous loading is the process of loading resources or modules that blocks subsequent code execution; Asynchronous loading: does not block the execution of subsequent code;

For an example, create the following directory;

| -- a.js
| -- index.js
| -- c.js

Copy the code
// a.js
console.log('a.js file execution ');
const importFun = () = > {
  console.log(require('./c').c);
}

importFun()


module.exports = {
  importFun
}
Copy the code
// index.js
const A = require('./a');
console.log('index.js execution ');
Copy the code
// c.js
console.log('The operation of C.JS');

const c = 3

module.exports = {
  c
}

Copy the code

Run node index.js

// a.js file execution
// c.js runs
/ / 3
// execute index.js
Copy the code

We’ll see that the contents of require block subsequent code execution. Since c.js is printed first and then index.js, require() is loaded synchronously;

// a.js
console.log('a.js file execution ');
export const importFun = () = > {
  import('./c.js').then(({c}) = >{
    console.log(c)
  })
}

importFun()

Copy the code
// index.js
import {importFun} from './a.js'
console.log('index.js execution ');
Copy the code
// c.js
console.log('The operation of C.JS');

export const c = 3

Copy the code
/ / the result
// a.js file execution
// execute index.js
// c.js runs
/ / 3
Copy the code

Import () loads resources asynchronously because c.js is printed after index.js and does not block subsequent code execution.

Summary: These are the differences between CommonJS and ESModule

The CommonJS module outputs a copy of the value, while the ES6 module outputs a reference to the value. The CommonJS module require() is a synchronously loaded module, while the ES6 module import command is asynchronously loaded, with a separate module-dependent parsing phase