CommonJS (CJS) and ECMAScript Modules (ESM) are the two main systems used in JavaScript to organize, import, and export code across files.

Key Differences

  • Syntax:
    • CommonJS uses require() and module.exports.
    • ESM uses import and export.
  • Loading Mechanism:
    • CommonJS loads modules synchronously (blocking) at runtime.
    • ESM loads modules asynchronously and supports top-level await.
  • Standardization:
    • CommonJS is the original module format built specifically for Node.js.
    • ESM is the official W3C/ECMAScript standard supported natively in modern web browsers and Node.js.
    • CommonJS does not support reliable tree-shaking (dead code elimination) because exports are dynamic and not statically analyzable.
    • ESM supports static analysis, allowing bundlers to drop unused code cleanly.
  • File Extensions & Config:
    • CommonJS uses .cjs or default .js (unless overridden).
    • ESM uses .mjs, or .js when "type": "module" is declared in package.json.
  • Global Variables:
    • CommonJS provides direct access to __dirname and __filename.
    • ESM does not have these globals; instead, it relies on import.meta.url.

Feature Comparison

Feature CommonJS (CJS) ECMAScript Modules (ESM)
Syntax require() / module.exports import / export
Loading Synchronous (blocking) Asynchronous (non-blocking)
Browser Support No (needs a bundler) Yes (native)
Tree-Shaking Limited / Not supported Fully supported
Default in Node.js Yes (for .js files) Yes (when configured)

Which Should You Use?

  • Use ESM as the default choice for all new projects, modern libraries, and browser-based applications.
  • Use CommonJS primarily when maintaining legacy Node.js codebases, working with older tools that lack ESM support, or when migrating would cause high disruption.