Amina Bešlija
Amina Bešlija

Node Modules at 'War': Why CommonJS and ES Modules Can’t Get Along

Dan Fabulich is a Principal Engineer at Redfin. (We’re hiring!) In Node 14, there are now two kinds of scripts: there are old-style CommonJS (CJS) scripts and new-style ESM scripts (aka MJS). CJS scripts use require() and module.exports; ESM scripts use import and export. ESM and CJS are completely different animals. Superficially, ESM looks very similar to CJS, but their implementations couldn’t be more different. One of them is a honey bee, and the other is a murder hornet. Here are the rules, which I’ll explain in more detail below: You can’t require() ESM scripts; you can only import ESM scripts, like this: import {foo} from 'foo' CJS scripts can’t use static import statements like the one above. CJS scripts can use asynchronous dynamic import() to use ESM, but that's a hassle, compared to synchronous require. ESM scripts can import CJS scripts, but only by using the “default import” syntax import _ from 'lodash', not the “named import” syntax import {shuffle} from 'lodash', which is a hassle if the CJS script uses named exports. ESM scripts can require() CJS scripts, even with named exports, but it’s typically not worth the trouble, because it requires even more boilerplate, and, worst of all, bundlers like Webpack and Rollup don’t/won’t know how to work with ESM scripts that use require(). CJS is the default; you have to opt-in to ESM mode. You can opt-in to ESM mode by renaming your script from .js to .mjs. Alternately, you can set "type": "module" in package.json, and then you can opt-out of ESM by renaming scripts from .js to .cjs. (You can even tweak just an individual subdirectory by putting a one-line {"type": "module"} package.json file in there.)


Node Modules at 'War': Why CommonJS and ES Modules Can’t Get Along #javascriptba #javascript #nodejs #reactjs #angularjs #vuejs #meteorjs #typescript #jquery #emberjs #denojs #bosnia