Hiprup

What is the difference between CommonJS and ES Modules?

Two module systems for sharing code between files.

  • CommonJS — Node's original system: require() to import, module.exports to export. Synchronous, loaded at runtime.

  • ES Modules — the standard: import / export. Static, asynchronous, works in browsers and modern Node.

  • Static analysis — ESM's fixed structure enables tree shaking; CommonJS is dynamic.

Direction of travel: ES Modules are the modern standard; CommonJS lingers in older Node code.

// CommonJS
const fs = require('fs');             // Import
const { readFile } = require('fs');   // Destructured import
module.exports = { add, subtract };   // Export
module.exports = MyClass;             // Default export

// ES Modules
import fs from 'fs';                  // Default import
import { readFile } from 'fs';        // Named import
import * as fs from 'fs';             // Namespace import
export function add(a, b) { return a + b; }  // Named export
export default class MyClass {}       // Default export

// Dynamic import (ESM — like require but async)
const module = await import('./module.js');

// Interop
// ESM can import CJS (usually works)
// CJS cannot require() ESM (must use dynamic import())

CJS uses require (sync) and module.exports. ESM uses import/export (async, static). Dynamic import() loads modules on demand (works in both systems).

ESM enables tree shaking because imports are statically analyzable. CJS cannot require ESM — use await import() instead.

CJS = require/module.exports (sync, dynamic, Node.js). ESM = import/export (async, static, standard). ESM enables tree shaking.

Know the interop: ESM can import CJS, CJS must use dynamic import() for ESM. ESM is the recommended future.

What is the difference between CommonJS and ES Modules? | Hiprup