17

I'm considering moving a large browser-based code base over to CommonJS (it's an AngularJS 1.x application written in TypeScript). The application has circular dependencies, so I think RequireJS is out of the question.

How does Browserify handle circular dependencies? Are there different categories of circular dependencies that are/aren't supported? Or any tips for working with circular dependencies with CommonJS/Browserify?

Eric
  • 5,842
  • 7
  • 42
  • 71

1 Answers1

2

Browserify does not add special treatment to cyclic dependencies and the behavior is inherited from Node.

It goes as shown in Node Modules documentation which I'm integrally quoting it below:


When there are circular require() calls, a module might not have finished executing when it is returned.

Consider this situation:

a.js:

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');

b.js:

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');

main.js:

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);

When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.

By the time main.js has loaded both modules, they're both finished. The output of this program would thus be:

$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true

Careful planning is required to allow cyclic module dependencies to work correctly within an application.

Andre Figueiredo
  • 12,930
  • 8
  • 48
  • 74