Node.js Core Modules
Built-in superpowers — no npm install required. These modules ship with every Node.js installation.
The Essential Six
fsFile system — read, write, watch files and directories
pathCross-platform file path manipulation — join, resolve, extname
httpRaw HTTP server and client — the foundation Express builds on
eventsEventEmitter — the pub/sub pattern used throughout Node
streamProcess data in chunks — essential for large files and I/O
osOperating system info — CPU count, memory, platform, homedir
Hands-On: Each Module in Action
const fs = require('fs/promises'); // promise-based API (prefer this)
// Reading a file
const content = await fs.readFile('./data.json', 'utf-8');
const data = JSON.parse(content);
// Writing a file (creates if not exists, overwrites if exists)
await fs.writeFile('./output.json', JSON.stringify(data, null, 2));
// Appending to a file
await fs.appendFile('./log.txt', `[${new Date().toISOString()}] Event\n`);
// Checking if a file exists
try {
await fs.access('./config.json');
console.log('Config exists');
} catch {
console.log('Config missing — using defaults');
}
// Listing directory contents
const files = await fs.readdir('./src');
console.log(files); // ['index.js', 'routes.js', ...]
const path = require('path');
// Join path segments (OS-aware — uses / on Mac/Linux, \ on Windows)
path.join('/users', 'alice', 'docs'); // '/users/alice/docs'
path.join(__dirname, '../config'); // resolves relative to this file
// Resolve to absolute path
path.resolve('./src/index.js'); // '/home/user/project/src/index.js'
// Decompose a path
path.basename('/home/user/file.txt'); // 'file.txt'
path.dirname('/home/user/file.txt'); // '/home/user'
path.extname('/home/user/file.txt'); // '.txt'
// __dirname = directory of the current file (CommonJS only)
// In ES Modules use: import.meta.dirname
console.log(__dirname); // e.g. '/home/user/project/src'
console.log(__filename); // e.g. '/home/user/project/src/index.js'
const http = require('http');
// A minimal JSON API server (what Express wraps for you)
const server = http.createServer((req, res) => {
// Parse URL and method
const { url, method } = req;
// Route: GET /health
if (url === '/health' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
return;
}
// 404 fallback
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not found' }));
});
server.listen(3000, () => console.log('Listening on :3000'));
// This routing logic is exactly what Express automates
const { EventEmitter } = require('events');
// EventEmitter is the observer pattern built into Node
// Most Node.js objects (streams, servers) extend it
class OrderService extends EventEmitter {
placeOrder(order) {
// Do business logic...
this.emit('order:placed', order); // fire event with data
}
}
const orders = new OrderService();
// Subscribe to events — decoupled from the emitter
orders.on('order:placed', (order) => {
console.log(`Send confirmation email for order ${order.id}`);
});
orders.on('order:placed', (order) => {
console.log(`Trigger inventory check for order ${order.id}`);
});
orders.placeOrder({ id: 123, item: 'Widget' });
// Both listeners fire
const fs = require('fs');
// Problem: reading a 2GB file with readFile() loads it ALL into RAM
// Solution: streams — process it in small chunks
// Pipe a read stream to a write stream (e.g. copy a large file)
const readable = fs.createReadStream('./huge-file.csv');
const writable = fs.createWriteStream('./output.csv');
readable.pipe(writable);
readable.on('end', () => console.log('Done!'));
// In an Express route, stream a file to the response
app.get('/download', (req, res) => {
res.setHeader('Content-Type', 'text/csv');
fs.createReadStream('./report.csv').pipe(res);
// Data flows to the client chunk-by-chunk — never fully in RAM
});
http module. When something goes wrong in Express, you end up reading the Node.js docs. Knowing what's underneath makes you a far better debugger.
The global object
Node.js provides several globals — available without requiring anything:
console.log() // you know this one
setTimeout(fn, ms) // schedule a callback after ms milliseconds
setInterval(fn, ms) // repeat a callback every ms milliseconds
clearTimeout(id) // cancel a timeout
process.env // object of environment variables (process.env.PORT)
process.exit(1) // exit the process (0 = success, non-zero = error)
process.argv // command-line arguments as an array
__dirname // absolute path of current file's directory (CommonJS)
__filename // absolute path of current file (CommonJS)
🧠 Check Your Understanding
Go Deeper
Primary source: Node.js docs — fs module — the reference you'll return to most.
Also read: path module docs — short and worth 10 minutes.
Ask your teacher: "When should I use streams instead of readFile?" or "Explain EventEmitter with a real backend example."