CommonJS Modules
Every Node.js application is made up of modules — files that export functionality and import it from other files. Before ES Modules arrived in Node.js, CommonJS was the only module system. You’ll encounter it constantly in the Node.js ecosystem.
What a module is
Section titled “What a module is”A module is any .js or .ts file. By default, everything in a file is private — variables, functions, classes. You explicitly choose what to expose.
module.exports
Section titled “module.exports”To make something available to other files, assign it to module.exports:
function add(a, b) { return a + b}
function subtract(a, b) { return a - b}
module.exports = { add, subtract }require()
Section titled “require()”To use exports from another file, call require() with the file path:
const { add, subtract } = require('./math')
console.log(add(2, 3)) // 5console.log(subtract(10, 4)) // 6The ./ prefix means “relative to the current file.” Without it, Node.js looks in node_modules.
Module resolution order
Section titled “Module resolution order”When you require('something'), Node.js checks in this order:
- Built-in modules (
fs,path,http) — no file needed - Relative paths (
./math,../utils) — looks for the exact file - node_modules — looks for a package with that name
const fs = require('fs') // built-inconst math = require('./math') // relative fileconst express = require('express') // from node_modulesThe module wrapper
Section titled “The module wrapper”Node.js wraps every module in a function before executing it:
(function(exports, require, module, __filename, __dirname) { // your module code runs here})This is why __filename (the current file’s path) and __dirname (the current file’s directory) are available in any CommonJS module — they’re injected as arguments. It’s also why require is available without importing it.
Default exports
Section titled “Default exports”You can export a single value as the entire module.exports:
module.exports = function greet(name) { return `Hello, ${name}!`}const greet = require('./greet')console.log(greet('Alice')) // Hello, Alice!When you’ll see CommonJS
Section titled “When you’ll see CommonJS”Many npm packages still ship CommonJS. You’ll see it in:
- Older Node.js tutorials and codebases
- Some npm packages (check their
package.jsonfor"main"field) - Configuration files like
eslint.config.cjs
The Bulletin API uses ES Modules (next lesson), but understanding CJS helps when you hit require in the wild.
Exercise
Section titled “Exercise”- Create
src/utils/math.tsthat exportsadd,subtract, andmultiplyfunctions. - Create
src/test.tsthat requires the math module and logs results of each function. - Run with
tsx src/test.tsand verify the output.
module.exportsmakes values available to other files.require('./path')imports those values.- Module resolution: built-ins → relative paths → node_modules.
__filenameand__dirnameare injected by Node.js’s module wrapper.- CommonJS is still common in the ecosystem even though ES Modules are now preferred.