ESM vs CommonJS in JavaScript: Interop, Packaging, and Build Behavior

LowIntermediateJavascript
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

Complete interview answer for ESM vs CommonJS covering static vs dynamic loading, live bindings, Node package exports, interop pitfalls, and why module format affects bundling, optimization, and runtime behavior.

Answer

Definition (above the fold)

ES Modules (ESM) are the standard JavaScript module system with static import/export syntax that tools can analyze ahead of time. CommonJS (CJS) is the older Node.js module system using require and module.exports. Interviewers care less about syntax and more about interop and packaging decisions in real projects.

Mental model

Think of ESM as statically analyzable graph edges and CJS as runtime-evaluated module loading. Static analysis enables better tree-shaking and optimization. Runtime flexibility in CJS can help legacy systems but complicates analysis.

Dimension

ESM

CommonJS

Import style

import/export

require/module.exports

Analysis

Static graph known at build time

More dynamic, harder to optimize

Bindings

Live bindings

Exported object values

Async loading

Native support with import()

Primarily synchronous require

Tooling fit

Best for modern bundlers and browsers

Strong legacy Node ecosystem support

Choose format based on ecosystem, runtime, and optimization goals.

Runnable example #1: equivalent module exports

JAVASCRIPT
// math.mjs (ESM)
export const add = (a, b) => a + b;
export default function sum(arr) {
  return arr.reduce((acc, n) => acc + n, 0);
}

// math.cjs (CommonJS)
const addCjs = (a, b) => a + b;
function sumCjs(arr) {
  return arr.reduce((acc, n) => acc + n, 0);
}
module.exports = { add: addCjs, sum: sumCjs };
                  

Same behavior is possible in both systems, but the package boundary and import style define interoperability and optimization quality.

Runnable example #2: package exports map for safer consumption

JSON
{
  "name": "ui-kit",
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.js"
}
                  

Interop pitfall

Symptom

Fix

Default vs named import mismatch

undefined is not a function at runtime

Align export style and import syntax explicitly

Mixed module entrypoints

Consumers resolve wrong file in bundlers

Use consistent exports map

Transpiler masking module type issues

Works in dev but breaks in production runtime

Validate with runtime-native tests

Dynamic require in shared package

Poor tree-shaking and larger bundles

Prefer static imports where possible

Most interview follow-ups focus on these production failures.

Common pitfalls

      • Publishing ambiguous package entrypoints without an exports map.
      • Assuming all tools resolve CJS/ESM the same way.
      • Using CJS patterns in ESM codebases and losing optimization opportunities.
      • Not testing package consumption in both import and require scenarios.

When to use / when not to use

Use ESM by default for modern frontend and new libraries. Keep CJS compatibility only when you must support legacy runtimes or tooling. Do not keep dual formats indefinitely without ownership, because dual-package maintenance can create drift and subtle bugs.

Interview follow-ups

Q1: Why does ESM help optimization? A: Static imports allow bundlers to prune unused code more safely.
Q2: How do you ship both formats? A: Build dual outputs and define deterministic exports conditions.
Q3: What breaks most often? A: Default/named interop mismatches and inconsistent runtime/tool resolver behavior.

Implementation checklist / takeaway

Prefer ESM-first packaging, define explicit exports conditions, test import/require consumers, and avoid ambiguous entrypoints. Strong interview answers connect module format to runtime correctness and bundle quality.

Similar questions
Guides
34 / 61