How do CommonJS and ES6 Modules handle loop dependencies?

(CommonJS/ES6 Module) : juejin.cn/post/695936…

Generally speaking, cyclic dependencies should be avoided in engineering as far as possible, because from the perspective of software design, one-way dependencies are more clear, while cyclic dependencies will bring certain complexity.

  • But when the complexity of the project increases to a sufficient scale, it is easy to have hidden cyclic dependencies. In short, it is easy to detect whether there is A direct cyclic dependency between modules A and B. But what happens is that A depends on B, AND B depends on C, and C depends on D, and then D depends on A. When there are too many intermediate modules, it is difficult to find an implicit cyclic dependency between A and B.

Actual code Examples

Directory structure:

├── Main.js ├─ bar.js ├─ aaA.jsCopy the code

Commonjs loop dependencies (resolved in comments)

// main.js
const bar = require('./bar.js')
console.log('Currently in main.js :', bar) / / {}
module.exports = 'In main.js'

// bar.js
const main = require('./main.js')
console.log('Currently in bar.js :', main)
module.exports = 'bar. Within the js'

// Execute node./main.js with output:The current is within bar.js: {}// Parsing: when executed in bar.js, there is no export before main.js is finished, and the default export is empty objectIt is currently in main.js: bar.jsCopy the code

Es6 Module loop dependency handling (parsing in comments)

// main.js
import bar from './bar.js'
console.log('Currently in main.js :', bar)
export default 'In main.js'

// bar.js
import main from './main.js'
console.log('Currently in bar.js :', main)
export default 'bar. Within the js'

// run webpack-dev-server xx to start the service.Currently inside bar.js:undefined  / / resolution: compile to the bar. The js, in the main, js has not yet been compiled, it have nothing to compile the map to the main variables, is undefinedIt is currently in main.js: bar.jsCopy the code

The solution

Only the ES6 Module can be used, because only the dynamic mapping of its values can obtain the changed state

The core idea

  1. Values exported by the ES6 Module are dynamically mapped
  2. Wrap it with function so that loading doesn’t happen immediately
  3. Use a variable to solve the problem of repeated calls (closures)
// main.js (for packaging convenience, here main.js is only used as the entry, aaa and bar loop dependency)
import aaa from './aaa.js'
aaa('main')

// aaa.js
import bar from './bar.js'
function aaa (name) {
  console.log('Currently in aaA.js :', name)
  bar('aaa')}export default aaa

// bar.js
import aaa from './aaa.js'
let time = false
function bar (name) {
  if(! time) { time =true
    console.log('Currently in bar.js :', name)
    aaa('bar')}}export default bar

// run webpack-dev-server xx to start the service.Js: main: bar. Js: aaa: barCopy the code

Refer to Webpack Practice: Getting Started, Advancing and Tuning (Ju Yuhao)