Suggest an editImprove this articleRefine the answer for “ESM vs CommonJS”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**CommonJS** is Node.js's module system, where modules load synchronously at runtime and imports are copies of values. **ES Modules (ESM)** is the standardized ECMAScript system, where modules are analyzed at compile time (parse-time), load asynchronously, and imports are "live" bindings. **Key point:** CommonJS is a dynamic, synchronous, Node.js-specific system where imports execute at startup, while ES Modules is a static, asynchronous, standardized system where dependencies are known in advance and import creates live references.Shown above the full answer for quick recall.Answer (EN)Image## 1. In short: the main idea | System | Core concept | |---|---| | **CommonJS (CJS)** | Modules are loaded **at runtime**, synchronously, line by line. | | **ES Modules (ESM)** | Modules are analyzed **at compile time** (parse-time), loaded **asynchronously**, with strict dependencies and "live" imports. | ## 2. Philosophy of the systems ### CommonJS Created **for Node.js** (in 2009) to run JS on the server. - Everything is synchronous (since files are on the local disk); - Each file is an isolated module; - Code executes top to bottom on the first `require()`; - Imports are **a copy of values**, not "live references". Example: ```javascript // math.js module.exports = { x: 1 }; // app.js const math = require('./math'); console.log(math.x); // 1 math.x = 2; // changes only the local copy ``` ### ES Modules Created **for the JavaScript language** (ES6, 2015), so that one standard would work in both browsers and Node.js. - Loading is **asynchronous**, declarative; - Imports are **static** - known before the code runs; - Optimization is possible, including *tree-shaking*; - Imports are **live bindings**, that is, "live" references rather than copies. Example: ```javascript // counter.js export let count = 0; export function inc() { count++; } // app.js import { count, inc } from './counter.js'; inc(); console.log(count); // 1 (the value updated) ``` ## 3. Conceptual differences | Concept | CommonJS | ES Modules | |---|---|---| | **Load time** | At runtime | Before execution (parse-time) | | **Imports** | Dynamic (`require()`) | Static (`import`) | | **Binding type** | Values are copied | Live references (live bindings) | | **Execution order** | Top to bottom | Determined by dependencies | | **Asynchrony** | Synchronous | Asynchronous | | **Optimization** | Not possible (runtime) | Tree-shaking possible | | **Context** | `this` = `module.exports` | `this` = `undefined` | | **Caching** | After the first call | Yes, but with "live" values | | **Ecosystem** | Node.js, older packages | Modern JS, browsers, Node 13+ | | **Architecture** | Imperative | Declarative | | **Compatibility** | Server only | Universal (server + client) | ## 4. The difference in loading and compilation timing ### CommonJS: - The line `require()` executes -> the file is read -> the code runs. - So the path can be a variable: ```javascript const lib = require(condition ? './a' : './b'); ``` It works because this is an ordinary function. ### ES Modules: - Imports must be **at the top of the file** and **cannot be dynamic**: ```javascript import x from './a'; // valid if (cond) import x from './b'; // error ``` - Node.js and the browser know in advance which dependencies are needed, and can load them **in parallel** before the code runs. ## 5. The difference in module structure Node.js "wraps" a CommonJS module in an internal function: ```javascript (function (exports, require, module, __filename, __dirname) { // your code }); ``` So there is: - `require` - `module.exports` - `__dirname` - `__filename` This is absent in ESM: - instead of `__dirname` -> `import.meta.url` - `require` is unavailable ## 6. Caching behavior In CommonJS, a module executes once and is **cached**: ```javascript const a = require('./a'); const b = require('./a'); console.log(a === b); // true ``` In ESM there is also a cache, but imports remain **live** (if the variables are exported as let/const): ```javascript import { counter } from './a.js'; ``` If the module updates the value, all imports see the update. ## 7. Tree-shaking and optimization Tree-shaking is the removal of unused code (in Webpack, Rollup, Vite, etc.). - **CJS:** not possible, because imports are dynamic; - **ESM:** possible, because dependencies are static. Example: ```javascript import { used } from './utils.js'; // the bundler knows only used is needed ``` ## 8. Compatibility | Scenario | CommonJS | ES Modules | |---|---|---| | Using older packages | Yes | Sometimes needs `createRequire()` | | SSR / server | Excellent | Excellent (Node 13+) | | Browsers | No | Yes | | Tree-shaking | No | Yes | | Top-level await | No | Yes | ## 9. "Live" vs "dead" imports (example) ### CommonJS: ```javascript // counter.js let count = 0; module.exports = { count, inc() { count++; } }; // app.js const c = require('./counter'); c.inc(); console.log(c.count); // 0 (a copy) ``` ### ES Modules: ```javascript // counter.mjs export let count = 0; export function inc() { count++; } // app.mjs import { count, inc } from './counter.mjs'; inc(); console.log(count); // 1 (a live reference) ``` ## 10. Conceptually: the key differences | Parameter | CommonJS | ESM | |---|---|---| | Basis | Node.js (server) | ECMAScript standard | | Execution model | Executes immediately (runtime) | Analyzes dependencies first | | Imports | Allowed anywhere | Top level only | | Access to the environment | `require`, `module`, `exports`, `__dirname` | `import.meta.url`, `import/export` | | Compatibility | Many older libraries | Modern bundlers and browsers | | Performance | Faster for local requires | More efficient in large projects | ## In one sentence: > **CommonJS** is a dynamic, synchronous, Node.js-specific module system where imports execute at startup. > **ES Modules** is a static, asynchronous, standardized system where dependencies are known in advance and import creates live references.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.