4 ms·
There is a valid discussion to be had about whether the Node.js ecosystem disruption of moving from CJS to ESM is worth the benefits, but the assertion that it'
by aravindet 5y ago
There is a valid discussion to be had about whether the Node.js ecosystem disruption of moving from CJS to ESM is worth the benefits, but the assertion that it's technically worse isn't accurate. A few things ESM does better in Node.js:
1. Asynchronous dynamic import() vs. blocking require(): allows the program to continue while a module is being dynamically loaded.
2. Circular dependencies: ESM correctly resolves most of them, while CJS does not. [example below] I believe this is possible because ESM top-level imports and exports are resolved before JS execution begins, while require() is resolved when called (while JS is already executing.)
3. Reserved keywords `import` and `export` vs. ordinary identifiers require, exports and module: Allows tooling to be simpler and not have to analyze variable scope and shadowing to identify dependencies.
I haven't really encountered #3, but I can say I've benefited from #1 and #2 in real-world Node.js projects using ESM.
----
Circular dependencies example:
// a.js
const b = require('./b.js');
module.exports = () => b();
// b.js
const a = require('./a.js');
module.exports = () => console.log('Works!');
a();
Running this with "node b.js" gives "TypeError: b is not a function" inside a.js, while the equivalent ESM code correctly prints 'Works!'. To solve this in CJS, we have to always use "named exports" (exports.a = ... rather than module.exports = ...) and avoid destructuring in the top-level require (i.e. always do const a = require(...) and call it as a.a() elsewhere)