JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeQuestionsjavascript
PrevNext

Learn the concept

Modules

javascript
mid
modules

What is the difference between ES Modules (ESM) and CommonJS (CJS)?

modules
esm
commonjs
import
export
bundling
Quick Answer

ES Modules use import/export syntax with static analysis and are asynchronously loaded. CommonJS uses require/module.exports with synchronous loading. ESM is the modern standard for browsers and modern Node.js, while CJS is the legacy Node.js module system.

Detailed Explanation

ES Modules (ESM):

  • Syntax: import / export
  • Static — imports resolved at parse time (enables tree-shaking)
  • Asynchronous loading
  • Top-level await supported
  • this is undefined at top level
  • File extension: .mjs or "type": "module" in package.json
  • Works in browsers natively (<script type="module">)

CommonJS (CJS):

  • Syntax: require() / module.exports
  • Dynamic — imports resolved at runtime
  • Synchronous loading
  • this is module.exports at top level
  • File extension: .cjs or default in Node.js
  • Does not work in browsers natively

Key differences: | Feature | ESM | CJS | |---------|-----|-----| | Syntax | import/export | require/module.exports | | Loading | Async | Sync | | Analysis | Static (tree-shakeable) | Dynamic | | Browser | Native support | Needs bundler | | Node.js | Supported (all current versions) | Default (legacy) |

Note: Node.js 22.12+ supports require(esm) by default, allowing CJS code to import ES modules directly.

Code Examples

ESM syntaxJavaScript
// Named exports
export const PI = 3.14;
export function add(a, b) { return a + b; }

// Default export
export default class Calculator { /* ... */ }

// Importing
import Calculator, { PI, add } from './math.js';
import * as math from './math.js';

// Dynamic import (code splitting)
const module = await import('./heavy-module.js');

// Re-exporting
export { add } from './math.js';
export { default as Calculator } from './calc.js';

Real-World Applications

Use Cases

Library Publishing

Shipping npm packages with both ESM and CJS builds using package.json exports for maximum compatibility

Code Splitting

Using dynamic import() to load features on demand in SPAs, reducing initial bundle size

Monorepo Architecture

Sharing modules across packages in a monorepo using workspace imports with proper ESM/CJS resolution

Mini Projects

Dual-format Package

beginner

Create an npm package that exports both ESM and CJS using package.json conditional exports field

Dynamic Plugin Loader

intermediate

Build a plugin system using dynamic import() to load modules at runtime based on configuration

Industry Examples

Vite

ESM-first dev server with instant HMR, using native browser ES modules during development

tsdown

Rolldown-powered bundler that outputs both ESM and CJS formats from TypeScript source, successor to tsup

Node.js

Conditional exports in package.json allow dual ESM/CJS packages with the exports field

Resources

MDN - JavaScript modules

docs

Node.js - ESM and CJS

docs
Previous
What is currying and partial application in JavaScript?
Next
When should you use Map and Set instead of plain objects and arrays?
PrevNext