Exploring Node.js Core Modules
Node.js core modules are built-in modules that come with Node.js installation. They provide essential functionality for file system operations, networking, path manipulation, operating system interactions, and much more. Mastering these modules is the foundation of every Node.js application.
1. fs (File System) Module — Working with Files
The fs module provides an API for interacting with the file system. It has both synchronous and asynchronous methods.
Common fs Methods
| Method | Description | Async Version |
|---|---|---|
readFile | Read a file | fs.promises.readFile |
writeFile | Write to a file | fs.promises.writeFile |
appendFile | Append to a file | fs.promises.appendFile |
mkdir | Create a directory | fs.promises.mkdir |
readdir | Read directory contents | fs.promises.readdir |
stat | Get file/directory stats | fs.promises.stat |
unlink | Delete a file | fs.promises.unlink |
rmdir | Delete a directory | fs.promises.rmdir |
exists | Check if file exists | fs.promises.access |
rename | Rename a file | fs.promises.rename |
copyFile | Copy a file | fs.promises.copyFile |
createReadStream | Stream file content | — |
createWriteStream | Stream write to file | — |
Production Example — Read/Write Files
const fs = require('fs').promises;
const path = require('path');
// ✅ Production-ready: Async/await with error handling
async function readUserData(filePath) {
try {
const data = await fs.readFile(filePath, 'utf8');
return JSON.parse(data);
} catch (err) {
if (err.code === 'ENOENT') {
console.error('File not found:', filePath);
return null;
}
console.error('Error reading file:', err.message);
throw err;
}
}
async function writeUserData(filePath, data) {
try {
// Ensure directory exists
const dir = path.dirname(filePath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8');
console.log('Data written successfully');
} catch (err) {
console.error('Error writing file:', err.message);
throw err;
}
}
// Usage
const userData = await readUserData('./data/users.json');
await writeUserData('./data/users.json', { name: 'John', age: 30 });
Streaming Large Files
const fs = require('fs');
const { pipeline } = require('stream');
const { promisify } = require('util');
const pipelineAsync = promisify(pipeline);
// ✅ Production: Stream large files without memory issues
async function copyLargeFile(source, destination) {
const readStream = fs.createReadStream(source, { highWaterMark: 64 * 1024 });
const writeStream = fs.createWriteStream(destination);
// Handle errors
readStream.on('error', (err) => console.error('Read error:', err));
writeStream.on('error', (err) => console.error('Write error:', err));
// Using pipeline for proper backpressure handling
await pipelineAsync(readStream, writeStream);
console.log('File copied successfully');
}
readFileSync, writeFileSync) in request handlers. They block the event loop. Always use the fs.promises API or callback-based async methods.
2. path Module — Cross-Platform Path Handling
The path module provides utilities for working with file and directory paths, automatically handling platform differences (Windows vs. Unix).
| Method | Description | Example |
|---|---|---|
join | Join path segments | path.join('/usr', 'local', 'bin') |
resolve | Resolve an absolute path | path.resolve('src', 'app.js') |
dirname | Get directory name | path.dirname('/usr/local/bin') |
basename | Get filename | path.basename('/usr/local/bin') |
extname | Get file extension | path.extname('file.txt') |
parse | Parse path into object | path.parse('/usr/local/bin') |
relative | Get relative path | path.relative('/usr', '/usr/local/bin') |
isAbsolute | Check if path is absolute | path.isAbsolute('/usr/local/bin') |
Production Examples
const path = require('path');
// ✅ Always use path.join for cross-platform compatibility
const configPath = path.join(__dirname, 'config', 'app.json');
// ✅ Use path.resolve for absolute paths
const absolutePath = path.resolve('node_modules', 'express');
// ✅ Parse a path
const parsed = path.parse('/home/user/project/src/index.js');
// {
// root: '/',
// dir: '/home/user/project/src',
// base: 'index.js',
// ext: '.js',
// name: 'index'
// }
// ✅ Get file info
const dir = path.dirname(__filename);
const base = path.basename(__filename);
const ext = path.extname(__filename);
console.log('File:', base); // 'app.js'
console.log('Directory:', dir); // '/home/user/project'
console.log('Extension:', ext); // '.js'
3. http/https Module — Building Web Servers
The http and https modules provide the foundation for building web servers and making HTTP requests.
Production HTTP Server
const http = require('http');
const url = require('url');
const querystring = require('querystring');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
// Route handling
if (pathname === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Hello, World!</h1>');
} else if (pathname === '/api/users') {
const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(users));
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
// ✅ Production: Handle errors gracefully
server.on('error', (err) => {
console.error('Server error:', err);
});
server.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Making HTTP Requests
const http = require('http');
const https = require('https');
// ✅ Production: Fetch data from external API
function fetchData(url) {
return new Promise((resolve, reject) => {
const client = url.startsWith('https') ? https : http;
client.get(url, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (err) {
reject(new Error('Invalid JSON response'));
}
});
}).on('error', (err) => {
reject(err);
});
});
}
// Usage
try {
const data = await fetchData('https://api.example.com/users');
console.log(data);
} catch (err) {
console.error('Failed to fetch data:', err.message);
}
4. os Module — Operating System Information
The os module provides information about the operating system, which is useful for monitoring, diagnostics, and system-specific behavior.
| Method | Description | Example Output |
|---|---|---|
cpus | CPU core information | Array of CPU objects |
totalmem | Total system memory | 16777216 (16GB) |
freemem | Free system memory | 4294967296 (4GB) |
platform | OS platform | 'linux', 'darwin', 'win32' |
release | OS release version | '5.15.0-67-generic' |
hostname | System hostname | 'production-server' |
type | OS type | 'Linux', 'Windows_NT' |
uptime | System uptime (seconds) | 86400 (1 day) |
loadavg | System load average | [1.5, 0.8, 0.5] |
Production Monitoring Example
const os = require('os');
// ✅ Production: System health monitoring
function getSystemInfo() {
const totalMemGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2);
const freeMemGB = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);
const usedMemGB = (totalMemGB - freeMemGB).toFixed(2);
const memUsagePercent = ((1 - os.freemem() / os.totalmem()) * 100).toFixed(2);
return {
platform: os.platform(),
release: os.release(),
hostname: os.hostname(),
uptime: `${Math.floor(os.uptime() / 3600)} hours, ${Math.floor((os.uptime() % 3600) / 60)} minutes`,
cpuCores: os.cpus().length,
cpuModel: os.cpus()[0]?.model || 'Unknown',
totalMemory: `${totalMemGB} GB`,
freeMemory: `${freeMemGB} GB`,
usedMemory: `${usedMemGB} GB`,
memoryUsage: `${memUsagePercent}%`,
loadAverage: os.loadavg().join(', '),
};
}
// Health check endpoint
app.get('/health', (req, res) => {
const info = getSystemInfo();
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
system: info
});
});
5. events Module — Event Emitter
The events module implements the Node.js event-driven architecture. It's used by many core modules and is essential for building loosely coupled systems.
Event Emitter Examples
const EventEmitter = require('events');
// ✅ Production: Create a custom event emitter
class OrderService extends EventEmitter {
createOrder(orderData) {
// Validate order
if (!orderData.items || orderData.items.length === 0) {
this.emit('error', new Error('Order must have at least one item'));
return;
}
// Process order
this.emit('order.created', orderData);
// Simulate async processing
setTimeout(() => {
this.emit('order.processed', {
...orderData,
status: 'processed',
processedAt: new Date().toISOString()
});
}, 2000);
return { id: Date.now(), ...orderData };
}
}
// Usage
const orderService = new OrderService();
// Listen to events
orderService.on('order.created', (order) => {
console.log('📦 Order created:', order.id);
// Send confirmation email
});
orderService.on('order.processed', (order) => {
console.log('✅ Order processed:', order.id);
// Update inventory
});
orderService.on('error', (err) => {
console.error('❌ Order error:', err.message);
});
// Create an order
orderService.createOrder({
items: [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }]
});
Best Practices for Event Emitters
- Always handle 'error' events — unhandled errors crash the process.
- Limit listeners — use
setMaxListeners()to avoid memory leaks. - Remove listeners when no longer needed.
- Use
once()for one-time events to avoid memory leaks.
// ✅ Proper event listener management
class Service extends EventEmitter {
constructor() {
super();
this.setMaxListeners(20); // Increase limit
// Use once for one-time events
this.once('ready', () => {
console.log('Service ready');
});
// Use off to remove listeners
this.on('data', (data) => { /* process data */ });
this.off('data', this._dataHandler);
}
}
6. crypto Module — Cryptographic Functions
The crypto module provides cryptographic functionality including hashing, encryption, signing, and random number generation.
| Method | Description | Use Case |
|---|---|---|
createHash | Create a hash | Password hashing, checksums |
createHmac | HMAC generation | API authentication |
randomBytes | Generate random bytes | API keys, tokens |
createCipheriv | Encrypt data | Data encryption |
createDecipheriv | Decrypt data | Data decryption |
pbkdf2 | Password-based key derivation | Secure password storage |
Production Examples
const crypto = require('crypto');
// ✅ 1. Password hashing (PBKDF2)
async function hashPassword(password) {
const salt = crypto.randomBytes(32).toString('hex');
const iterations = 100000;
const keylen = 64;
const digest = 'sha512';
return new Promise((resolve, reject) => {
crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
if (err) reject(err);
resolve({
hash: derivedKey.toString('hex'),
salt: salt,
iterations: iterations
});
});
});
}
async function verifyPassword(password, storedHash, salt) {
const iterations = 100000;
const keylen = 64;
const digest = 'sha512';
return new Promise((resolve, reject) => {
crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
if (err) reject(err);
resolve(derivedKey.toString('hex') === storedHash);
});
});
}
// ✅ 2. Generate secure API key
function generateApiKey() {
return crypto.randomBytes(32).toString('hex');
}
// ✅ 3. HMAC for API authentication
function generateHmacSignature(payload, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(JSON.stringify(payload));
return hmac.digest('hex');
}
// ✅ 4. Hash a file for checksum
function hashFile(data) {
const hash = crypto.createHash('sha256');
hash.update(data);
return hash.digest('hex');
}
// Usage
const apiKey = generateApiKey();
console.log('API Key:', apiKey);
const hashed = await hashPassword('securePassword123');
const isValid = await verifyPassword('securePassword123', hashed.hash, hashed.salt);
console.log('Password valid:', isValid);
7. util Module — Utility Functions
The util module provides various utility functions for debugging, type checking, and promise handling.
Production Examples
const util = require('util');
const fs = require('fs');
// ✅ 1. promisify — Convert callback-based functions to promises
const readFileAsync = util.promisify(fs.readFile);
const writeFileAsync = util.promisify(fs.writeFile);
async function readConfig() {
try {
const data = await readFileAsync('./config.json', 'utf8');
return JSON.parse(data);
} catch (err) {
console.error('Failed to read config:', err.message);
return null;
}
}
// ✅ 2. types — Type checking
const types = require('util/types');
console.log(types.isDate(new Date())); // true
console.log(types.isRegExp(/test/)); // true
// ✅ 3. inspect — Better object inspection
const obj = {
name: 'John',
nested: {
deep: {
values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
}
};
console.log(util.inspect(obj, {
depth: null,
colors: true,
showHidden: true
}));
// ✅ 4. deprecate — Mark functions as deprecated
const oldApi = util.deprecate(
() => { console.log('Old API called'); },
'oldApi() is deprecated. Use newApi() instead.'
);
oldApi(); // Shows deprecation warning
8. url & querystring Modules — URL Handling
The url and querystring modules provide utilities for parsing and manipulating URLs and query strings.
const url = require('url');
const querystring = require('querystring');
// ✅ Parse URLs
const urlString = 'https://api.example.com/users?page=2&limit=10&sort=asc';
const parsedUrl = new URL(urlString);
console.log(parsedUrl.hostname); // 'api.example.com'
console.log(parsedUrl.pathname); // '/users'
console.log(parsedUrl.searchParams.get('page')); // '2'
console.log(parsedUrl.searchParams.get('limit')); // '10'
// ✅ Build URLs
const params = new URLSearchParams({
page: 3,
limit: 20,
sort: 'desc'
});
const newUrl = new URL('https://api.example.com/products');
newUrl.search = params.toString();
console.log(newUrl.toString()); // https://api.example.com/products?page=3&limit=20&sort=desc
// ✅ Parse query string (legacy)
const qs = 'page=2&limit=10&sort=asc';
const parsedQs = querystring.parse(qs);
console.log(parsedQs); // { page: '2', limit: '10', sort: 'asc' }
// ✅ Stringify query string
const stringified = querystring.stringify({ page: 2, limit: 10 });
console.log(stringified); // 'page=2&limit=10'
9. Core Modules Quick Reference
| Module | Common Use Cases | Production Importance |
|---|---|---|
| fs | File reading/writing, logging, config storage | 🔴 Critical |
| path | File path handling, cross-platform compatibility | 🔴 Critical |
| http/https | Web servers, API clients, external requests | 🔴 Critical |
| os | System monitoring, health checks | 🟡 Important |
| events | Event-driven architecture, loose coupling | 🟡 Important |
| crypto | Security, hashing, encryption, authentication | 🔴 Critical |
| util | Debugging, promisification, type checking | 🟢 Nice to have |
| url | URL parsing, query string handling | 🟡 Important |
10. Production-Ready Checklist
- ✅ Always use fs.promises — Avoid callback-based methods; use async/await.
- ✅ Never use synchronous methods —
readFileSync,writeFileSyncblock the event loop. - ✅ Use path.join — For cross-platform compatibility.
- ✅ Implement streaming — Use streams for large files to avoid memory issues.
- ✅ Handle errors — Always handle errors in file operations and network requests.
- ✅ Set max listeners — Use
setMaxListeners()for event emitters. - ✅ Use crypto.randomBytes — For generating secure tokens and API keys.
- ✅ Use PBKDF2 — For password hashing with high iteration count.
- ✅ Monitor system resources — Use os module for health checks.
- ✅ Promisify callbacks — Use
util.promisifyfor consistent async patterns. - ✅ Validate URLs — Always validate and sanitize URLs and query strings.
- ✅ Remove event listeners — Prevent memory leaks by removing unused listeners.
Ready to master Node.js?
Build scalable, high-performance backend applications with Node.js. Learn from industry experts with hands-on projects.
.png)