Node.js logoNode.jsINTERMEDIATE

Node.js Core Modules

Node.js core modules cheat sheet covering fs, http, path, crypto, streams, events, and process with practical code examples.

15 min read
nodejsfshttpcryptostreamseventsprocessos

Sign in to mark items as known and track your progress.

Sign in

File System (fs)

Read, write, and manipulate files and directories

File Operations

Read, write, delete files with async and sync methods

javascript
// Read file
const data = fs.readFileSync('file.txt', 'utf8');
fs.readFile('file.txt', 'utf8', (err, data) => {});

// Write file
fs.writeFileSync('file.txt', 'content');
fs.appendFileSync('file.txt', 'more');

// Delete/Check
fs.unlinkSync('file.txt');
fs.existsSync('file.txt');
🟢 Essential - Every Node.js app deals with files
💡 Use async methods (fs.promises) to avoid blocking
⚠️ Always handle errors in file operations
📌 Use path.join() for cross-platform paths
⚡ Stream large files instead of reading all at once
🔗 Related: fs-extra for additional utilities

Path Module

Work with file and directory paths across platforms

javascript
const path = require('path');

// Join paths
path.join('/users', 'john', 'documents', 'file.txt');

// Get parts
path.dirname('/users/john/file.txt');  // /users/john
path.basename('/users/john/file.txt'); // file.txt
path.extname('file.txt');              // .txt

// Resolve absolute
path.resolve('file.txt');
🟢 Essential - Handle paths correctly on all OS
💡 Always use path.join() not string concatenation
📌 __dirname is current file's directory
⚡ path.resolve() creates absolute paths
⚠️ Windows uses \ while Unix uses /
🔗 Related: process.cwd() for working directory

Directory Operations

Create, read, and remove directories

javascript
const fs = require('fs').promises
const path = require('path')

// Create directory (recursive)
await fs.mkdir('path/to/dir', { recursive: true })

// Read directory contents
const files = await fs.readdir('./src')
// With file types
const entries = await fs.readdir('./src', { withFileTypes: true })
const dirs = entries.filter(e => e.isDirectory())

// Remove directory
await fs.rmdir('path/to/dir')
// Remove with contents (Node 14+)
await fs.rm('path/to/dir', { recursive: true, force: true })
💡 Use recursive: true to create nested directories
⚡ readdir with withFileTypes avoids extra stat calls
⚠️ fs.rm() with force: true is like rm -rf (dangerous)
📌 Watch has platform-specific limitations
🔗 Related: glob for pattern matching
filesystemdirectories

HTTP & HTTPS

Create servers and make HTTP requests

HTTP Server

Create HTTP servers to handle web requests

javascript
const http = require('http');

// Create server
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World');
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});
🟢 Essential - Foundation of web servers in Node.js
💡 Use Express.js for production applications
📌 Server emits events: request, connection, close
⚡ Use cluster module for multi-core utilization
⚠️ Handle server errors to prevent crashes
🔗 Related: https module for SSL/TLS

HTTP Client Requests

Make HTTP requests to external APIs and services

javascript
const http = require('http');

// GET request
http.get('http://api.example.com/data', (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => console.log(data));
});

// POST request
const req = http.request(options, (res) => {
  // Handle response
});
req.write(JSON.stringify(data));
req.end();
💡 Consider using axios or node-fetch for easier API
📌 Response is a readable stream
⚡ Set timeout to prevent hanging requests
⚠️ Always handle network errors
🟢 Essential for API integration
🔗 Related: https.request() for secure requests

Process & OS

Interact with system processes and operating system

Process Module

Access command line arguments, environment, and control process

javascript
// Arguments & Environment
console.log(process.argv);
console.log(process.env.NODE_ENV);

// Exit
process.exit(0);

// Current directory
process.cwd();

// Memory usage
process.memoryUsage();

// Event handlers
process.on('uncaughtException', (err) => {
  console.error(err);
});
🟢 Essential - Control Node.js runtime behavior
💡 process.env for environment variables
📌 process.argv contains command line arguments
⚠️ process.exit() immediately terminates (use carefully)
⚡ process.nextTick() for async scheduling
🔗 Related: dotenv for .env file loading

OS Module

Get operating system information and utilities

javascript
const os = require('os');

// System info
os.platform();  // 'darwin', 'linux', 'win32'
os.arch();      // 'x64', 'arm'
os.hostname();
os.cpus();
os.totalmem();
os.freemem();

// User info
os.userInfo();
os.homedir();
💡 Useful for system monitoring and diagnostics
📌 os.platform() returns darwin, win32, linux
⚡ os.cpus() for CPU info and core count
🟢 Essential for cross-platform apps
🔗 Related: systeminformation for detailed stats

Child Process

Execute system commands and spawn new processes

javascript
const { spawn, exec, execSync } = require('child_process')

// Execute simple command (callback-based)
exec('ls -la', (error, stdout, stderr) => {
  if (error) console.error(\`Error: \${error}\`)
  console.log(stdout)
})

// Synchronous execution (blocks)
const result = execSync('npm list', { encoding: 'utf-8' })
console.log(result)

// Spawn for streaming/long-running
const ls = spawn('ls', ['-la', '/usr'])
ls.stdout.on('data', (data) => {
  console.log(\`Output: \${data}\`)
})
💡 exec for simple commands, spawn for complex/streaming
⚠️ Sanitize user input to prevent command injection
📌 fork() is specifically for Node.js scripts
⚡ Use worker_threads for CPU-intensive tasks instead
🔗 Related: execa for better child process handling
processsystem

Crypto & Buffer

Cryptography operations and binary data handling

Crypto Module

Cryptographic functionality for hashing, encryption, and security

javascript
const crypto = require('crypto');

// Hash
const hash = crypto.createHash('sha256')
  .update('password')
  .digest('hex');

// Random
const token = crypto.randomBytes(32).toString('hex');

// Encrypt/Decrypt
const cipher = crypto.createCipher('aes192', 'password');
const encrypted = cipher.update('text', 'utf8', 'hex');
🟢 Essential - Security and data integrity
💡 Use crypto.randomBytes() for secure random values
⚠️ Never use Math.random() for security
📌 bcrypt is better for password hashing
⚡ Use streaming API for large files
🔗 Related: jsonwebtoken for JWT tokens

Buffer Module

Handle binary data and convert between encodings

javascript
// Create buffers
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.from('Hello');
const buf3 = Buffer.from([1, 2, 3]);

// Read/Write
buf1.write('Hello');
console.log(buf1.toString());

// Compare
Buffer.compare(buf1, buf2);
💡 Buffers are fixed-size byte arrays
📌 Use Buffer.from() not new Buffer() (deprecated)
⚡ Buffers are more memory efficient than strings
⚠️ Be careful with buffer overflows
🔗 Related: stream.Buffer for streaming operations

Streams & Events

Handle streaming data and event-driven programming

Streams

Process data piece by piece without loading all into memory

javascript
const fs = require('fs');

// Readable stream
const readable = fs.createReadStream('input.txt');
readable.on('data', chunk => console.log(chunk));

// Writable stream
const writable = fs.createWriteStream('output.txt');
writable.write('Hello');

// Pipe
readable.pipe(writable);
🟢 Essential - Handle large files and real-time data
💡 Four types: Readable, Writable, Duplex, Transform
⚡ Streams save memory and improve performance
📌 pipe() handles backpressure automatically
⚠️ Always handle stream errors
🔗 Related: stream/promises for async iteration

Event Emitter

Create and handle custom events for async communication

javascript
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter();

// Listen for event
emitter.on('event', (data) => {
  console.log('Event:', data);
});

// Emit event
emitter.emit('event', 'data');

// Once listener
emitter.once('close', () => {});
🟢 Essential - Core of Node.js event-driven architecture
💡 Many Node.js objects extend EventEmitter
📌 removeListener() to prevent memory leaks
⚠️ Default max 10 listeners (setMaxListeners to change)
⚡ once() for one-time event handlers
🔗 Related: events.EventEmitter is the base class

Utilities & Advanced

Utility functions and advanced Node.js features

URL & QueryString

Parse and construct URLs and query strings

javascript
const { URL } = require('url')
const querystring = require('querystring')

// Modern URL API (recommended)
const myUrl = new URL('https://example.com:8000/path?name=John&age=30')
console.log({
  hostname: myUrl.hostname,
  pathname: myUrl.pathname,
  searchParams: myUrl.searchParams.get('name')
})

// Modify URL
myUrl.searchParams.append('role', 'admin')
myUrl.pathname = '/users/profile'
console.log(myUrl.href)

// Parse query string
const query = querystring.parse('name=John&age=30&hobbies=coding&hobbies=music')
// Result: { name: 'John', age: '30', hobbies: ['coding', 'music'] }
🟢 Essential - URL parsing for web applications
💡 Use new URL() instead of legacy url.parse()
📌 URLSearchParams for easy query manipulation
⚡ URL validation happens in constructor
🔗 Related: path module for file paths
urlutilities

Util Module

Utility functions for debugging and promisification

javascript
const util = require('util')
const fs = require('fs')

// Promisify callback-based functions
const readFile = util.promisify(fs.readFile)
const data = await readFile('file.txt', 'utf8')

// Format strings (like printf)
const msg = util.format('%s:%d', 'Server', 8080)
// 'Server:8080'

// Deep inspect objects
const obj = { a: 1, b: { c: 2, d: [3, 4] } }
console.log(util.inspect(obj, { 
  showHidden: true, 
  depth: null, 
  colors: true 
}))
💡 promisify() converts callbacks to promises
📌 util.inspect() is great for debugging
⚡ TextEncoder/Decoder for UTF-8 conversion
🟢 Essential for modernizing callback code
🔗 Related: console.dir() for simple inspection
utilitiesdebugging

Worker Threads

Run JavaScript in parallel threads for CPU-intensive tasks

javascript
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads')

if (isMainThread) {
  // Main thread code
  const worker = new Worker(__filename, {
    workerData: { iterations: 1000000 }
  })
  
  worker.on('message', (result) => {
    console.log('Result:', result)
  })
  
  worker.on('error', (err) => {
    console.error('Worker error:', err)
  })
  
  worker.postMessage({ cmd: 'START' })
} else {
  // Worker thread code
  parentPort.on('message', (msg) => {
    if (msg.cmd === 'START') {
      // CPU-intensive task
      let result = 0
      for (let i = 0; i < workerData.iterations; i++) {
        result += Math.sqrt(i)
      }
      parentPort.postMessage(result)
    }
  })
}
🔴 Advanced - For CPU-intensive parallel processing
💡 Workers run in separate V8 isolates
⚠️ No shared memory (use SharedArrayBuffer carefully)
⚡ Better than child_process for JavaScript code
📌 Not for I/O operations (use async/await instead)
🔗 Related: cluster for network server scaling
parallelperformance

Cluster Module

Scale Node.js apps across multiple CPU cores

javascript
const cluster = require('cluster')
const http = require('http')
const os = require('os')

if (cluster.isMaster) {
  const cpuCount = os.cpus().length
  
  console.log(\`Master \${process.pid} spawning \${cpuCount} workers\`)
  
  // Fork workers
  for (let i = 0; i < cpuCount; i++) {
    cluster.fork()
  }
  
  cluster.on('exit', (worker, code, signal) => {
    console.log(\`Worker \${worker.process.pid} died\`)
    console.log('Starting new worker...')
    cluster.fork()
  })
} else {
  // Workers share server port
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end(\`Worker \${process.pid} responded\\n\`)
  }).listen(8000)
  
  console.log(\`Worker \${process.pid} started\`)
}
🟢 Essential for production Node.js servers
💡 Workers share server ports automatically
⚡ Scales to all CPU cores for better performance
📌 Master process manages workers
⚠️ Workers die independently, implement restart logic
🔗 Related: pm2 for production process management
scalingperformance

Modern Node.js (Built-in)

Built-in APIs added to recent Node.js LTS releases

node: Import Prefix

Explicitly import built-in modules to avoid name collisions

javascript
// Prefer the node: prefix for built-in modules (Node 16+)
import fs from 'node:fs/promises'
import path from 'node:path'
import { createServer } from 'node:http'
import { fileURLToPath } from 'node:url'
import { setTimeout as sleep } from 'node:timers/promises'

// Why: the prefix guarantees you get the built-in, not a same-named npm
// package, and makes intent obvious to humans and tools.
💡 Prefer `node:` everywhere — uniform and unambiguous
⚡ Eliminates a class of name-collision and shadowing bugs
📌 Works on Node 16+; required for `node:test` and a few newer modules
🎯 eslint-plugin-n has a `prefer-node-protocol` rule to enforce it
esmimportsmodern

Built-in fetch & Web Streams

fetch, Request, Response, Headers, FormData, AbortController — all global

javascript
// Built-in fetch (stable since Node 21) — no node-fetch needed
const res = await fetch('https://api.example.com/users')
if (!res.ok) throw new Error('HTTP ' + res.status)
const users = await res.json()

// Streaming a response
const res = await fetch('https://example.com/big.csv')
for await (const chunk of res.body) {
  process.stdout.write(chunk)
}

// Aborting a slow request
const ac = new AbortController()
const timer = setTimeout(() => ac.abort(), 5000)
try {
  const r = await fetch(url, { signal: ac.signal })
} finally {
  clearTimeout(timer)
}
💡 No more `node-fetch` — `fetch` is global in Node 18+ (stable in 21)
⚡ AbortSignal.timeout(ms) replaces the manual setTimeout dance
📌 Body is a Web ReadableStream — works with `for await` and pipeThrough
🎯 Backed by undici; drop down to undici directly for pooling control
fetchhttpstreamsmodern

node:test Runner

Built-in test runner with describe / it / assert — no Jest needed

javascript
import { test, describe, it, before, after, mock } from 'node:test'
import assert from 'node:assert/strict'

test('adds two numbers', () => {
  assert.equal(1 + 1, 2)
})

describe('User', () => {
  it('starts inactive', () => {
    const u = new User()
    assert.equal(u.active, false)
  })
})

// Run with:  node --test
// Run a single file: node --test test/user.test.js
// Watch mode:        node --test --watch
💡 No Jest, no vitest — `node --test` is enough for most projects
⚡ Built-in mock + mock.timers + watch mode + parallel files
📌 `node:assert/strict` is the assertion lib — same API as Jest expect-ish
🎯 TS works via `--experimental-strip-types --test` on Node 22.6+
testingmodern