CommonJS is the module system Node.js launched with, and it still powers a huge share of existing Node.js code. This lesson covers require(), module.exports, and the details that trip people up when switching between CommonJS and ES modules.
What Is CommonJS?
CommonJS is a module specification that predates native JavaScript modules. Node.js adopted it in 2009 because JavaScript itself had no built-in module system at the time. Every .js file in a CommonJS project is wrapped in a function that provides require, module, exports, __filename, and __dirname automatically.
You export values by assigning to module.exports (or adding properties to the shorthand exports object), and you consume them elsewhere with require(), which reads and executes the target file synchronously the first time, then returns a cached result on every subsequent call.
module.exports is the actual object returned by require(). Whatever you assign to it becomes the public interface of that file.
CommonJS Syntax
module.exports = value; // export a single default value
exports.name = value; // export a named property (shorthand)
const x = require('./file.js'); // import a local file
const pkg = require('some-pkg'); // import an installed package
module.exports replaces the entire export object; use it for a single default export.
exports is a shorthand reference to module.exports, don't reassign exports itself directly.
require() is synchronous, it blocks until the target module has fully loaded.
Circular require() calls are allowed but can return a partially-completed module.
CommonJS Cheatsheet
The essential CommonJS patterns you'll see in most existing Node.js codebases.
Pattern
Example
Notes
Default export
module.exports = fn;
One value represents the whole module
Named exports
exports.a = 1; exports.b = 2;
Multiple named values
Destructured import
const { a, b } = require('./x');
Pull out specific named exports
Default import
const fn = require('./x');
Use when the module exports one value
Built-in module
const fs = require('node:fs');
node: prefix is optional but recommended
Current dir
__dirname
Absolute path to the current file's folder
The Module Wrapper Function
Node.js doesn't run your CommonJS file exactly as written, it wraps it in a function that supplies exports, require, module, __filename, and __dirname as parameters. This is why those identifiers are available without any import, and it's also why top-level this in a CommonJS file refers to module.exports, not the global object.
(function (exports, require, module, __filename, __dirname) {
// your file's code runs here
});
Module Caching
The first time a file is required, Node.js executes it and caches the resulting module.exports object by resolved file path. Every subsequent require() for that same path returns the cached object instantly, without re-running the file's code.
Mutating an exported object in one place affects every other file that required it.
Caching is why singletons (like a shared database connection) are easy to build with plain require().
Clearing the cache manually (delete require.cache[...]) is rare and mostly used in testing.
Common Mistakes
Reassigning exports = { ... } directly instead of module.exports = { ... }, which silently breaks the export (the local exports variable is replaced, not the real export).
Forgetting that require() is synchronous and can block on large or deeply nested dependency trees.
Relying on load order in circular require() situations without understanding partial exports.
Using .js files with CommonJS syntax inside a package.json configured with "type": "module".
Key Takeaways
CommonJS is Node's original, synchronous module system using require() and module.exports.
module.exports and exports both point to the same object by default, don't reassign exports directly.
Required modules are cached by resolved file path after their first load.
CommonJS files automatically receive __dirname, __filename, require, and module from a wrapper function.
Pro Tip
If a value you exported seems to be missing halfway through a file, check for a circular require(), the two files may be requiring each other before either has finished defining its exports.
You now understand CommonJS thoroughly. Next, learn the modern standard module system, ES Modules, and how it compares.