← Node.js from Scratch to Advanced
Lesson 2 of 3

How Node.js Modules Work

SoftwareBeginner

One File Isn't Enough Forever

As a program grows, keeping everything in one file gets unwieldy. Node lets you split code across files and pull pieces back in with require() - each file is a module, and whatever it assigns to module.exports is what other files get when they require it.

javascript
// math.js
function add(a, b) {
  return a + b;
}
module.exports = { add };

// app.js
const { add } = require('./math');
console.log(add(2, 3)); // 5

This require()/module.exports pattern is called CommonJS. Node also supports the newer import/export syntax (ES modules) - you will see both in real codebases, so it helps to recognize each.


Splitting code into modules is also what makes someone else's code reusable in your project - which is exactly what npm packages are.

Why This Matters Once Your App Grows

A todo-list script fits in one file. A real backend does not - by the time you have routes, database queries, validation, and a couple of background jobs, one file becomes a scroll-forever mess nobody wants to touch. Splitting by responsibility (`routes/users.js`, `db/queries.js`, `lib/email.js`) is what makes it possible for a second engineer to open the project and find what they're looking for without reading everything first.

A mistake that trips up a lot of people moving fast: two modules that `require()` each other. Module A needs something from B, B needs something from A - Node will not error immediately, but whichever one loads second gets a half-finished, possibly-empty version of the other. The fix is almost always to pull the shared thing into a third module both of them import instead.

CommonJS vs. ES Modules, Side by Side

You will see two different import syntaxes in real Node codebases, and it helps to recognize both on sight rather than being thrown by whichever one you didn't learn first.

javascript
// CommonJS (the original Node style)
const { add } = require('./math');
module.exports = { add };

// ES Modules (the newer, browser-matching style)
import { add } from './math.js';
export { add };

Which one runs depends on package.json's "type" field - "commonjs" (the default) or "module". Mixing them in one project without understanding this is a frequent source of confusing "Cannot use import statement outside a module" errors.