DEV Community

Cover image for TL;DR CommonJS vs ESM
Abbey Perini
Abbey Perini

Posted on • Updated on

TL;DR CommonJS vs ESM

In a Node.js project, you're likely to run into both CommonJS and ESM modules. Here's how to tell these module types apart at a glance.

CommonJS

CommonJS modules were part of Node.js when it was written in 2009. They run synchronously. Imports and exports are resolved and scripts are executed dynamically at runtime.

CommonJS uses __filename, __dirname, and NODE_PATH variables. ESM does not.

ESM

ECMAScript modules (ESM) or ES Modules were introduced in 2015 with JavaScriptES6 (also known as ECMAScript 2015 or ECMAScript 6). They are asynchronous. Imports and exports are resolved statically at parse time. The ESM module loader then downloads and parses scripts. Finally, the script executes.

ESM uses top-level await (await in a file outside an async function()). CommonJS does not.

Package.json

CommonJS:

"type": "commonjs"
Enter fullscreen mode Exit fullscreen mode

ESM:

"type": "module"
Enter fullscreen mode Exit fullscreen mode

Node.js throws an error for ESM modules without "type": "module", but I have yet to see a package.json with "type": "commonjs" in the wild.

Imports

CommonJS:

var module = require('file path');
Enter fullscreen mode Exit fullscreen mode

ESM:

import defaultStuff, { namedStuff } from 'file path';
Enter fullscreen mode Exit fullscreen mode

Exports

CommonJS:

// default
module.exports =

// default read-only
exports =

// named
module.exports.name =

// named read-only
exports.name =
Enter fullscreen mode Exit fullscreen mode

ESM:

// default
export default name

// named
export name
Enter fullscreen mode Exit fullscreen mode

File Extensions

Node.js will treat .js and .ts as CommonJS modules by default.

CommonJS uses .cjs for JavaScript and .cts for TypeScript.

ESM uses .mjs for JavaScript and .mts for TypeScript.

Runtime Environments

CommonJS is supported in all versions of Node.js.

ESM is supported in browsers and Node.js v12 or higher.

Strict Mode

CommonJS needs use strict at the top of the file.

ESM uses strict mode by default.

This

In CommonJS modules, this points at exports.

In ES modules, this is undefined.

Conclusion

At this point, I've upgraded a package and gotten an error like "ES Modules not supported" or "[module] is a CommonJS module, which may not support all module.exports as named exports" a few times. While troubleshooting, the search results I got were guides on how to write these modules or treatises on which one is better. This is the summary I wish I had before I had to jump down a rabbit hole just to understand an error.

Top comments (3)

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
manuartero profile image
Info Comment hidden by post author - thread only accessible via permalink
Manuel Artero Anguita ๐ŸŸจ • Edited

I've been struggling with all of this lately. My take is:nowadays prefer always ESM modules, CommonJs was a temporal best effort till official module system were a thing. Now, just use ESM modules :)
Common Js is slowly retiring.

Thanks for the post ^^

Collapse
 
webreflection profile image
Info Comment hidden by post author - thread only accessible via permalink
Andrea Giammarchi

for deeper analysis of pros and cons of each module system I suggest this post too:
webreflection.medium.com/cjs-vs-es...

Some comments have been hidden by the post's author - find out more