What are ES modules, and how do they differ from CommonJS?
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
requireruns 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.