What are ES modules, and how do they differ from CommonJS?

JavaScript ES6+ Intermediate 2–3 Yrs3–5 Yrs Conceptual 1 min read

Quick Answer

ES modules (import/export) are the standard JavaScript module system — statically analysable, so bundlers can tree-shake unused code, and they support top-level await. CommonJS (require/module.exports) is Node's older system — dynamic, synchronous, evaluated at call time.

ES modules are the built-in standard — import and export — and because the imports are static, the bundler can analyse them and drop code you don't use, which is tree-shaking. They also allow top-level await. CommonJS is Node's original system with require and module.exports; it's dynamic and synchronous, and require executes right where you write it. Browsers only do ES modules, Node does both, and mixing the two is the awkward part.

  • ESM imports are hoisted and resolved before execution; CJS require runs where it appears.
  • ESM exports are live bindings (you see updates to the exported value); CJS exports a snapshot object.
  • Browsers only support ESM (<script type="module">); Node supports both (.mjs / "type": "module").
  • Interop is fiddly — importing CJS from ESM often gives a default-export wrapper.