TL;DR CommonJS vs ESM

TL;DR CommonJS vs ESM

ยท

2 min read

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"

ESM:

"type": "module"

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');

ESM:

import defaultStuff, { namedStuff } from 'file path';

Exports

CommonJS:

// default
module.exports =

// default read-only
exports =

// named
module.exports.name =

// named read-only
exports.name =

ESM:

// default
export default name

// named
export name

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.

ย