CommonJS uses require/module.exports with synchronous loading, while ES Modules use import/export with static analysis support.
Node.js supports two module systems: CommonJS (CJS), the original Node.js module system, and ECMAScript Modules (ESM), the standard JavaScript module system.
CommonJS uses require() to import and module.exports or exports to export. Modules are loaded synchronously and cached after first load. require() can be called anywhere in the code, making it dynamic. Example: const fs = require('fs'); module.exports = { myFunction };
ES Modules use import and export statements. They're statically analyzable, meaning the module structure is determined at parse time, not runtime. This enables tree-shaking and better tooling. Example: import fs from 'fs'; export function myFunction() {}
To use ESM in Node.js: add "type": "module" to package.json (making .js files ESM), use .mjs extension for ESM files, or use .cjs for CommonJS in an ESM project.
Key differences: ESM imports are hoisted and executed first; CJS require() executes inline. ESM has named exports and a default export; CJS assigns to module.exports. ESM import() function provides dynamic imports, returning a promise. ESM doesn't have __dirname and __filename by default (use import.meta.url).
Most modern projects use ESM, but many npm packages still use CommonJS. Node.js handles interoperability: ESM can import CJS modules, but CJS requires dynamic import() to load ESM.
CommonJS uses require/module.exports with synchronous loading, while ES Modules use import/export with static analysis support.
Join our network of elite AI-native engineers.