Node.js Modules: require and module.exports
Master Node.js modules. Understand CommonJS, why modules exist, how require works, and code organization.
Node.js Modules: require and module.exports
What are Modules?
Modules let you split code into separate files. Each file is a **module** that can be imported and used in other files.
The Problem: Without Modules
``` app.js (1000+ lines) ├── Database functions ├── Authentication logic ├── User management ├── Email sending ├── File processing └── API routes
Problems: ❌ Hard to find code ❌ Hard to maintain ❌ Can't reuse code ❌ Variable name conflicts ❌ Everything in global scope ```
The Solution: Modules
``` project/ ├── app.js (main file) ├── db.js (database module) ├── auth.js (authentication module) ├── users.js (user module) ├── email.js (email module) └── routes.js (routes module)
Benefits: ✅ Organized code ✅ Easy to find ✅ Reusable ✅ No name conflicts ✅ Each module has its own scope ```
How Modules Work
``` ┌─────────────────────────────────┐ │ Module A (math.js) │ │ ┌──────────────────────────┐ │ │ │ function add() │ │ │ │ function subtract() │ │ │ │ │ │ │ │ module.exports = { │ │ │ │ add, subtract │ │ │ │ } │ │ │ └──────────────────────────┘ │ └─────────────────────────────────┘ │ │ require('./math') │ ┌──────────────▼────────────────────┐ │ Module B (app.js) │ │ ┌──────────────────────────┐ │ │ │ const math = require( │ │ │ │ './math' │ │ │ │ ) │ │ │ │ │ │ │ │ math.add(5, 3) │ │ │ └──────────────────────────┘ │ └─────────────────────────────────┘ ```
Benefits of Modules
**1. Code Organization** ``` Without Modules: 1 file, 1000 lines With Modules: 10 files, 100 lines each
Much easier to navigate! ```
**2. Reusability** ``` utils.js (shared utilities) ├── Used by app.js ├── Used by routes.js └── Used by auth.js
Write once, use everywhere! ```
**3. Scope Isolation** ``` math.js: const PI = 3.14 // Only in math.js
app.js: const PI = 3.14159 // Different variable!
No conflicts! ```
**4. Easier Testing** ``` Test each module independently math.js → test math.js auth.js → test auth.js ```
Why Modules?
Exporting from a Module
**Single export:** ```javascript // greet.js function greet(name) { return `Hello, ${name}!`; }
module.exports = greet; ```
**Multiple exports:** ```javascript // math.js function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
module.exports = { add, subtract }; // or module.exports.add = add; module.exports.subtract = subtract; ```
Importing with require
```javascript // app.js const greet = require('./greet'); const { add, subtract } = require('./math');
console.log(greet('Alice')); // Hello, Alice! console.log(add(5, 3)); // 8 console.log(subtract(10, 4)); // 6 ```
The ./ Matters!
```javascript // Your files - need ./ const myModule = require('./myModule');
// npm packages - no ./ const express = require('express');
// Built-in modules - no ./ const fs = require('fs'); ```
exports vs module.exports
```javascript // These are equivalent exports.add = add; module.exports.add = add;
// BUT this breaks exports exports = { add }; // ❌ Won't work module.exports = { add }; // ✅ Works ```
**Rule:** When exporting a single thing or replacing the whole export, use `module.exports`.
Exporting a Class
```javascript // User.js class User { constructor(name) { this.name = name; } sayHi() { return `Hi, I'm ${this.name}`; } }
module.exports = User; ```
```javascript // app.js const User = require('./User'); const alice = new User('Alice'); console.log(alice.sayHi()); ```
Module Caching
Modules are cached after first require: ```javascript const config1 = require('./config'); const config2 = require('./config');
// config1 === config2 (same object) ```
Organizing Modules
``` project/ ├── index.js ├── utils/ │ ├── index.js │ ├── format.js │ └── validate.js └── models/ ├── index.js └── User.js ```
```javascript // utils/index.js - re-export everything module.exports = { ...require('./format'), ...require('./validate') };
// app.js const utils = require('./utils'); ```
Key Takeaway
CommonJS modules use `require` to import and `module.exports` to export. Use `./` for local files, no prefix for packages. This system keeps your code organized and reusable.