CommonJS (require/module.exports) in Legacy Code
What Is CommonJS?
CommonJS (CJS) is the original Node.js module system. It uses require to import modules and module.exports to export values.
Basic Syntax
// math.js
function add(a, b) {
return a + b;
}
module.exports = { add };
// index.js
const { add } = require('./math');
console.log(add(2, 3));
Why CommonJS Exists
When Node was created, JavaScript had no official module system. CommonJS solved the problem for server-side development years before ES Modules were standardized.
Synchronous Loading
CommonJS modules are loaded synchronously. This works well in Node because files are local and loading is fast.
Module Wrapper
Node wraps each CJS file in a function:
(function (exports, require, module, __filename, __dirname) {
// your code here
});
This is why __dirname and __filename are available in CommonJS.
Exports vs module.exports
exports is a shortcut reference to module.exports. Reassigning exports breaks the link.
exports.value = 42; // correct
exports = {}; // wrong (does not export correctly)
CJS and ESM Differences
- CJS uses
require, ESM usesimport - CJS loads synchronously, ESM is asynchronous
- CJS allows dynamic require
- ESM supports top-level await
Interoperability Issues
Importing CommonJS from ESM works, but named exports may not behave as expected because CJS exports a single object.
Dynamic Require
const moduleName = './math'; const math = require(moduleName);
This dynamic behavior is not supported in static ESM imports.
When to Use CommonJS
- Legacy projects
- Large existing ecosystems
- Simpler backend setups
When to Avoid
- New TypeScript-first projects
- Shared browser + Node libraries
Production Insight
Many production systems still run on CommonJS. Understanding it is essential for debugging third-party packages and mixed-module environments.
Next Step
Next we will dive into module resolution and understand how Node decides which file to load when you import something.