CommonJS Modules in JavaScript
Introduction
CommonJS (require / module.exports) was Node’s original module system. Many older packages still use it. Modern projects prefer ES modules, but you will read and sometimes write CommonJS—especially in config files and legacy dependencies.
Prerequisites
Basic require
// greet.cjs — run: node greet.cjs
const path = require("node:path");
function greet(name) {
return `Hello, ${name}`;
}
module.exports = { greet };// main.cjs
const { greet } = require("./greet.cjs");
console.log(greet("Ada"));
console.log(path.basename(__filename));Use .cjs when "type": "module" is set in package.json but you need CommonJS syntax.
module.exports Patterns
// Export single function
module.exports = function add(a, b) {
return a + b;
};// Export object of members
module.exports = {
add(a, b) {
return a + b;
},
sub(a, b) {
return a - b;
},
};Built-in node: Prefix
// Explicit built-in modules (recommended)
const fs = require("node:fs");
const http = require("node:http");Works in both CJS and ESM (import fs from "node:fs").
__dirname and __filename
Available in CommonJS files:
const path = require("node:path");
console.log(__dirname);
console.log(path.join(__dirname, "data.json"));In ES modules use import.meta.url instead (Node provides fileURLToPath helpers).
Interop: ESM Importing CJS
// default import often maps to module.exports
import pkg from "legacy-package";Behavior depends on the package—check its docs.
When to Use CommonJS Today
- Maintaining older Node codebases
- Some tooling still expects
requirein config - Quick scripts without
"type": "module"
New learning projects: prefer ES modules.
Mini Example: Tiny Utils Package
// utils.cjs
function clamp(value, min, max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
module.exports = { clamp };// app.cjs
const { clamp } = require("./utils.cjs");
console.log(clamp(150, 0, 100));FAQ
Can I mix CJS and ESM in one project?
Yes with careful extensions (.cjs / .mjs) and package.json—keep boundaries clear.
require hoisting?
require runs at runtime—no hoisting like import.
exports vs module.exports?
Assign to module.exports; avoid rebinding exports itself.