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

javascript
// greet.cjs — run: node greet.cjs
const path = require("node:path");
 
function greet(name) {
  return `Hello, ${name}`;
}
 
module.exports = { greet };
javascript
// 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

javascript
// Export single function
module.exports = function add(a, b) {
  return a + b;
};
javascript
// Export object of members
module.exports = {
  add(a, b) {
    return a + b;
  },
  sub(a, b) {
    return a - b;
  },
};

Built-in node: Prefix

javascript
// 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:

javascript
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

javascript
// 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 require in config
  • Quick scripts without "type": "module"

New learning projects: prefer ES modules.

Mini Example: Tiny Utils Package

javascript
// utils.cjs
function clamp(value, min, max) {
  if (value < min) return min;
  if (value > max) return max;
  return value;
}
 
module.exports = { clamp };
javascript
// 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.

What comes next?

npm and package.json.