Skip to main content
Practice Problems

CommonJS vs es modules in Node.js

Module Systems in Node.js

Node.js supports two module systems: the original CommonJS (CJS) and the modern ES Modules (ESM). Understanding the differences is essential for writing compatible Node.js code.


CommonJS (CJS)

The default module system in Node.js since its inception.

js
// math.js β€” exporting function add(a, b) { return a + b; } module.exports = { add }; // main.js β€” importing const { add } = require('./math'); console.log(add(2, 3)); // 5

Key characteristics:

  • Uses require() / module.exports
  • Synchronous loading (blocks until module is loaded)
  • Loaded at runtime
  • Default in .js files unless "type": "module" in package.json

ES Modules (ESM)

The official ECMAScript standard, now fully supported in Node.js 12+.

js
// math.mjs β€” exporting export function add(a, b) { return a + b; } // main.mjs β€” importing import { add } from './math.mjs'; console.log(add(2, 3)); // 5

Key characteristics:

  • Uses import / export syntax
  • Asynchronous loading (better for tree-shaking)
  • Statically analyzed at parse time
  • Use .mjs extension OR set "type": "module" in package.json

Comparison Table

FeatureCommonJSES Modules
Syntaxrequire() / module.exportsimport / export
LoadingSynchronousAsynchronous
AnalysisRuntimeStatic (parse time)
Tree-shakingβŒβœ…
Top-level awaitβŒβœ…
__dirname / __filenameβœ…βŒ (use import.meta.url)
Default in Node.jsβœ…With "type":"module"

Interoperability

js
// ESM can import CJS: import { add } from './math.cjs'; // βœ… // CJS cannot require() ESM: const { add } = require('./math.mjs'); // ❌ Error! // CJS can use dynamic import() for ESM: const { add } = await import('./math.mjs'); // βœ…

Enabling ESM

Option 1: Use .mjs extension Option 2: Add to package.json:

json
{ "type": "module" }

Getting __dirname in ESM

js
import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);

Summary

Use ESM for new projects (it's the standard, supports tree-shaking and top-level await). Use CommonJS when working with legacy code or packages that don't support ESM yet.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems