Node.js Cheatsheet
Comprehensive quick reference for Node.js runtime, core modules, async operations, streams, file system, HTTP servers, npm, and best practices. Essential guide for Node.js 20+.
Table of Contents
- Prerequisites
- Installation & Version Management
- Core Modules
- File System Operations
- HTTP & Web Servers
- Async Operations
- Streams
- Process & Environment
- Error Handling
- Package Management
- Debugging & Profiling
- Best Practices
- Common Pitfalls
Prerequisites
Node.js Version: This cheatsheet targets Node.js 20.0+ (LTS). Some features require specific versions (noted inline).
System Requirements:
- macOS: 10.15+ (64-bit)
- Linux: Most distributions (64-bit)
- Windows: Windows 10/11 (64-bit) or WSL 2
Prerequisites:
- Basic JavaScript knowledge
- Command-line familiarity
- Understanding of async programming concepts
Installation & Version Management
Installation Commands π§
# Check Node.js versionnode --version# β v20.11.0
# Check npm versionnpm --version# β 10.2.4
# Check all versions (Node, npm, V8)node -p "process.versions"# β { node: '20.11.0', v8: '11.3.244.8', ... }
# Install Node.js via nvm (recommended)curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bashnvm install 20nvm use 20nvm alias default 20
# Install Node.js via Homebrew (macOS)brew install node@20
# Install Node.js via apt (Ubuntu/Debian)curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -sudo apt-get install -y nodejsVersion Management π
# List installed Node.js versions (nvm)nvm list
# Install specific versionnvm install 18.20.0
# Switch to versionnvm use 18.20.0
# Set default versionnvm alias default 20.11.0
# List available versionsnvm list-remote
# Check current versionnvm current# β v20.11.0Node.js REPL π»
# Start Node.js REPLnode
# In REPL:# .help - Show help# .exit - Exit REPL# .clear - Clear context# .load <file> - Load file# .save <file> - Save session
# Execute filenode script.js
# Execute with evalnode -e "console.log('Hello')"# β Hello
# Execute with stdinecho "console.log('Hi')" | node# β HiCore Modules
Module System π¦
// CommonJS (require/module.exports)const fs = require("fs");const { readFile } = require("fs"); // Named importmodule.exports = { myFunction };module.exports.myFunction = myFunction; // Named export
// ES Modules (import/export) - Node.js 12.20+, 14.13+, or 16+// In package.json: "type": "module"import fs from "fs";import { readFile } from "fs";import * as fs from "fs";export default myFunction;export { myFunction };export { myFunction as renamed };
// Mixed usage (CommonJS importing ES Module)const { default: myFunction } = await import("./module.mjs");
// ES Module importing CommonJSimport pkg from "./commonjs.cjs";const { myFunction } = pkg;Path Module πΊοΈ
const path = require("path");
// Join paths (handles separators)path.join("/foo", "bar", "baz/asdf", "quux", "..");// β '/foo/bar/baz/asdf'
// Resolve absolute pathpath.resolve("foo/bar", "/tmp/file/", "..", "a/../subfile");// β '/tmp/subfile'
// Get directory namepath.dirname("/foo/bar/baz/asdf/quux");// β '/foo/bar/baz/asdf'
// Get filenamepath.basename("/foo/bar/baz/asdf/quux.html");// β 'quux.html'
// Get filename without extensionpath.basename("/foo/bar/baz/asdf/quux.html", ".html");// β 'quux'
// Get extensionpath.extname("index.html");// β '.html'
// Parse path objectpath.parse("/home/user/dir/file.txt");// β { root: '/', dir: '/home/user/dir', base: 'file.txt', ext: '.txt', name: 'file' }
// Format path from objectpath.format({ dir: "/home/user/dir", base: "file.txt" });// β '/home/user/dir/file.txt'
// Normalize path (resolve . and ..)path.normalize("/foo/bar//baz/asdf/quux/..");// β '/foo/bar/baz/asdf'
// Check if absolute pathpath.isAbsolute("/foo/bar"); // β truepath.isAbsolute("./bar"); // β false
// Get relative pathpath.relative("/data/orandea/test/aaa", "/data/orandea/impl/bbb");// β '../../impl/bbb'URL Module π
const { URL } = require("url");
// Parse URLconst myURL = new URL("https://example.org:8080/foo/bar?abc=123#section");console.log(myURL.href); // β 'https://example.org:8080/foo/bar?abc=123#section'console.log(myURL.protocol); // β 'https:'console.log(myURL.hostname); // β 'example.org'console.log(myURL.port); // β '8080'console.log(myURL.pathname); // β '/foo/bar'console.log(myURL.search); // β '?abc=123'console.log(myURL.hash); // β '#section'
// URLSearchParamsconst params = new URLSearchParams("foo=bar&baz=qux");params.get("foo"); // β 'bar'params.set("foo", "new"); // Set valueparams.append("foo", "another"); // Add another valueparams.delete("baz"); // Delete paramparams.toString(); // β 'foo=new&foo=another'
// File URLconst fileUrl = new URL("file:///C:/path/to/file.txt");Util Module π οΈ
const util = require("util");
// Promisify callback-based functionconst fs = require("fs");const readFile = util.promisify(fs.readFile);const fileContent = await readFile("file.txt", "utf8");
// Inspect object (debugging)util.inspect({ a: 1, b: { c: 2 } }, { depth: 2, colors: true });
// Format string (like printf)util.format("%s:%s", "foo", "bar", "baz");// β 'foo:bar baz'
// Check typesutil.types.isDate(new Date()); // β trueutil.types.isRegExp(/abc/); // β trueutil.types.isPromise(Promise.resolve()); // β true
// Inherit (deprecated, use ES6 classes)util.inherits(MyStream, stream.Stream);
// Callbackify (convert promise to callback)const callbackFn = util.callbackify(asyncFn);callbackFn((err, result) => { /* ... */});Buffer Module π
const { Buffer } = require("buffer");
// Create bufferconst buf1 = Buffer.alloc(10); // Zero-filledconst buf2 = Buffer.allocUnsafe(10); // Uninitialized (faster)const buf3 = Buffer.from("hello"); // From stringconst buf4 = Buffer.from([1, 2, 3]); // From arrayconst buf5 = Buffer.from("hello", "utf8"); // With encoding
// Buffer operationsbuf1.write("hello", 0, "utf8");buf1.toString("utf8"); // β 'hello'buf1.toString("hex"); // β '68656c6c6f'buf1.toString("base64"); // β 'aGVsbG8='
// Buffer methodsbuf1.length; // β 10buf1.slice(0, 5); // β New buffer (shares memory)buf1.copy(buf2, 0, 0, 5); // Copy to another bufferBuffer.concat([buf1, buf2]); // Concatenate buffersBuffer.isBuffer(buf1); // β true
// Buffer comparisonbuf1.equals(buf2); // β falsebuf1.compare(buf2); // β -1, 0, or 1Crypto Module π
const crypto = require("crypto");
// Hashconst hash = crypto.createHash("sha256");hash.update("hello");hash.digest("hex");// β '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
// HMACconst hmac = crypto.createHmac("sha256", "secret-key");hmac.update("hello");hmac.digest("hex");
// Random bytescrypto.randomBytes(16, (err, buf) => { console.log(buf.toString("hex"));});
// Synchronous random bytesconst randomBuf = crypto.randomBytes(16);
// Create cipherconst cipher = crypto.createCipher("aes192", "password");let encrypted = cipher.update("hello", "utf8", "hex");encrypted += cipher.final("hex");
// Create decipherconst decipher = crypto.createDecipher("aes192", "password");let decrypted = decipher.update(encrypted, "hex", "utf8");decrypted += decipher.final("utf8");File System Operations
Reading Files π
const fs = require("fs");const fsPromises = require("fs").promises;
// Synchronous read (blocking)const data = fs.readFileSync("file.txt", "utf8");console.log(data);
// Asynchronous read (callback)fs.readFile("file.txt", "utf8", (err, data) => { if (err) throw err; console.log(data);});
// Promise-based read (Node.js 10+)const data = await fsPromises.readFile("file.txt", "utf8");
// Read with optionsconst data = await fsPromises.readFile("file.txt", { encoding: "utf8", flag: "r",});
// Read binary fileconst buffer = await fsPromises.readFile("image.png");Writing Files βοΈ
const fs = require("fs");const fsPromises = require("fs").promises;
// Synchronous writefs.writeFileSync("file.txt", "Hello World", "utf8");
// Asynchronous writefs.writeFile("file.txt", "Hello World", "utf8", (err) => { if (err) throw err; console.log("File written");});
// Promise-based writeawait fsPromises.writeFile("file.txt", "Hello World", "utf8");
// Append to filefs.appendFileSync("file.txt", "\nNew line", "utf8");await fsPromises.appendFile("file.txt", "\nNew line", "utf8");
// Write with optionsawait fsPromises.writeFile("file.txt", "content", { encoding: "utf8", mode: 0o666, flag: "w", // 'w' write, 'a' append, 'r+' read/write});Directory Operations π
const fs = require("fs");const fsPromises = require("fs").promises;
// Create directoryfs.mkdirSync("newdir");await fsPromises.mkdir("newdir");
// Create directory recursivelyfs.mkdirSync("path/to/dir", { recursive: true });await fsPromises.mkdir("path/to/dir", { recursive: true });
// Read directoryconst files = fs.readdirSync("dir");const files = await fsPromises.readdir("dir");
// Read directory with optionsconst files = await fsPromises.readdir("dir", { encoding: "utf8", withFileTypes: true, // Returns Dirent objects});
// Remove directoryfs.rmdirSync("dir");await fsPromises.rmdir("dir");
// Remove directory recursively (Node.js 14.14+)fs.rmSync("dir", { recursive: true });await fsPromises.rm("dir", { recursive: true });
// Check if path existsif (fs.existsSync("file.txt")) { // File exists}
// Check if path exists (async)const exists = await fsPromises .access("file.txt") .then(() => true) .catch(() => false);File Stats & Metadata π
const fs = require("fs");const fsPromises = require("fs").promises;
// Get file statsconst stats = fs.statSync("file.txt");const stats = await fsPromises.stat("file.txt");
// Check file typestats.isFile(); // β true/falsestats.isDirectory(); // β true/falsestats.isSymbolicLink(); // β true/false
// File propertiesstats.size; // File size in bytesstats.mtime; // Modified timestats.ctime; // Created timestats.mode; // File mode (permissions)stats.uid; // User IDstats.gid; // Group ID
// Watch file changesconst watcher = fs.watch("file.txt", (eventType, filename) => { console.log(`Event: ${eventType}, File: ${filename}`);});
// Watch directoryconst watcher = fs.watch("dir", { recursive: true }, (eventType, filename) => { console.log(`Event: ${eventType}, File: ${filename}`);});
watcher.close(); // Stop watchingFile Operations π
const fs = require("fs");const fsPromises = require("fs").promises;
// Copy filefs.copyFileSync("source.txt", "dest.txt");await fsPromises.copyFile("source.txt", "dest.txt");
// Copy with flagsawait fsPromises.copyFile("source.txt", "dest.txt", fs.constants.COPYFILE_EXCL);
// Rename/move filefs.renameSync("old.txt", "new.txt");await fsPromises.rename("old.txt", "new.txt");
// Delete filefs.unlinkSync("file.txt");await fsPromises.unlink("file.txt");
// Change permissionsfs.chmodSync("file.txt", 0o755);await fsPromises.chmod("file.txt", 0o755);
// Change ownershipfs.chownSync("file.txt", 1000, 1000);await fsPromises.chown("file.txt", 1000, 1000);
// Create symlinkfs.symlinkSync("target", "link");await fsPromises.symlink("target", "link");
// Read symlinkconst target = fs.readlinkSync("link");const target = await fsPromises.readlink("link");HTTP & Web Servers
HTTP Server π
const http = require("http");
// Create HTTP serverconst server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World\n");});
server.listen(3000, () => { console.log("Server running on http://localhost:3000");});
// Server with routingconst server = http.createServer((req, res) => { const { method, url } = req;
if (method === "GET" && url === "/") { res.writeHead(200, { "Content-Type": "text/html" }); res.end("<h1>Home</h1>"); } else if (method === "GET" && url === "/api/users") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify([{ id: 1, name: "John" }])); } else { res.writeHead(404); res.end("Not Found"); }});
server.listen(3000);HTTP Client π‘
const http = require("http");
// GET requestconst options = { hostname: "example.com", port: 80, path: "/api/data", method: "GET", headers: { "User-Agent": "Node.js", },};
const req = http.request(options, (res) => { let data = "";
res.on("data", (chunk) => { data += chunk; });
res.on("end", () => { console.log(JSON.parse(data)); });});
req.on("error", (error) => { console.error(error);});
req.end();
// GET request (simplified)http.get("http://example.com/api/data", (res) => { let data = ""; res.on("data", (chunk) => { data += chunk; }); res.on("end", () => { console.log(data); });});HTTPS Server & Client π
const https = require("https");const fs = require("fs");
// HTTPS serverconst options = { key: fs.readFileSync("key.pem"), cert: fs.readFileSync("cert.pem"),};
const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end("Hello HTTPS");});
server.listen(443);
// HTTPS clientconst options = { hostname: "example.com", port: 443, path: "/api/data", method: "GET", rejectUnauthorized: true, // Verify certificate};
const req = https.request(options, (res) => { // Handle response});
req.end();URL Parsing in HTTP Requests π
const http = require("http");const { URL } = require("url");
const server = http.createServer((req, res) => { const baseURL = `http://${req.headers.host}/`; const parsedUrl = new URL(req.url, baseURL);
// Access URL components parsedUrl.pathname; // β '/api/users' parsedUrl.search; // β '?id=123' parsedUrl.searchParams.get("id"); // β '123'
res.end("OK");});Async Operations
Promises β³
// Create promiseconst promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Success"); // or reject(new Error('Failed')); }, 1000);});
// Promise chainpromise .then((value) => { console.log(value); // β 'Success' return "Next value"; }) .then((value) => { console.log(value); // β 'Next value' }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Always executed"); });
// Promise.all (all must succeed)Promise.all([promise1, promise2, promise3]) .then((results) => { // All resolved }) .catch((error) => { // First rejection });
// Promise.allSettled (wait for all)Promise.allSettled([promise1, promise2]).then((results) => { // All settled (resolved or rejected)});
// Promise.race (first to settle)Promise.race([promise1, promise2]).then((result) => { // First resolved});
// Promise.any (first to resolve)Promise.any([promise1, promise2]).then((result) => { // First resolved});Async/Await π―
// Async functionasync function fetchData() { try { const response = await fetch("https://api.example.com/data"); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; }}
// Multiple async operationsasync function fetchMultiple() { // Sequential const data1 = await fetchData1(); const data2 = await fetchData2();
// Parallel const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
return { data1, data2 };}
// Async arrow functionconst fetchData = async () => { const data = await someAsyncOperation(); return data;};
// Top-level await (ES Modules, Node.js 14.8+)const data = await fetchData();Callbacks vs Promises vs Async/Await π
// Callback style (old)fs.readFile("file.txt", "utf8", (err, data) => { if (err) { console.error(err); return; } console.log(data);});
// Promise stylefs.promises .readFile("file.txt", "utf8") .then((data) => console.log(data)) .catch((err) => console.error(err));
// Async/await style (modern)try { const data = await fs.promises.readFile("file.txt", "utf8"); console.log(data);} catch (err) { console.error(err);}Event Loop Understanding π
// Microtasks vs Macrotasksconsole.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
process.nextTick(() => console.log("4"));
console.log("5");
// Output: 1, 5, 4, 3, 2// Order: sync β nextTick β promises β timers
// process.nextTick (highest priority)process.nextTick(() => { console.log("Next tick");});
// setImmediate (check phase)setImmediate(() => { console.log("Immediate");});
// setTimeout (timers phase)setTimeout(() => { console.log("Timeout");}, 0);Streams
Readable Streams π₯
const fs = require("fs");
// Create readable streamconst readable = fs.createReadStream("large-file.txt", { encoding: "utf8", highWaterMark: 64 * 1024, // 64KB chunks});
// Read datareadable.on("data", (chunk) => { console.log(`Received ${chunk.length} bytes`);});
readable.on("end", () => { console.log("Finished reading");});
readable.on("error", (err) => { console.error("Error:", err);});
// Pause and resumereadable.pause();readable.resume();
// Custom readable streamconst { Readable } = require("stream");
const readable = new Readable({ read() { this.push("chunk"); this.push(null); // End stream },});Writable Streams π€
const fs = require("fs");
// Create writable streamconst writable = fs.createWriteStream("output.txt");
// Write datawritable.write("Hello ");writable.write("World");writable.end("\nDone");
// Eventswritable.on("finish", () => { console.log("Finished writing");});
writable.on("error", (err) => { console.error("Error:", err);});
// Custom writable streamconst { Writable } = require("stream");
const writable = new Writable({ write(chunk, encoding, callback) { console.log(chunk.toString()); callback(); // Signal completion },});Transform Streams π
const { Transform } = require("stream");
// Transform stream (readable + writable)const transform = new Transform({ transform(chunk, encoding, callback) { // Transform data const upper = chunk.toString().toUpperCase(); this.push(upper); callback(); },});
// Usageprocess.stdin.pipe(transform).pipe(process.stdout);
// Example: Uppercase transformconst upperCase = new Transform({ transform(chunk, encoding, callback) { callback(null, chunk.toString().toUpperCase()); },});
fs.createReadStream("input.txt") .pipe(upperCase) .pipe(fs.createWriteStream("output.txt"));Piping Streams π
const fs = require("fs");
// Basic pipefs.createReadStream("input.txt").pipe(fs.createWriteStream("output.txt"));
// Pipe with error handlingconst readStream = fs.createReadStream("input.txt");const writeStream = fs.createWriteStream("output.txt");
readStream.pipe(writeStream);
readStream.on("error", (err) => { writeStream.destroy(); console.error("Read error:", err);});
writeStream.on("error", (err) => { readStream.destroy(); console.error("Write error:", err);});
// Pipe with transformconst { pipeline } = require("stream");const zlib = require("zlib");
pipeline( fs.createReadStream("input.txt"), zlib.createGzip(), fs.createWriteStream("output.txt.gz"), (err) => { if (err) { console.error("Pipeline failed:", err); } else { console.log("Pipeline succeeded"); } },);Process & Environment
Process Object π₯οΈ
// Process argumentsprocess.argv;// β ['/path/to/node', '/path/to/script.js', 'arg1', 'arg2']
// Environment variablesprocess.env.NODE_ENV;process.env.PORT || 3000;
// Process IDprocess.pid;
// Current working directoryprocess.cwd();process.chdir("/new/path");
// Exit processprocess.exit(0); // Successprocess.exit(1); // Error
// Exit handlersprocess.on("exit", (code) => { console.log(`Exiting with code ${code}`);});
process.on("beforeExit", (code) => { console.log("Before exit");});
// Uncaught exceptionprocess.on("uncaughtException", (err) => { console.error("Uncaught exception:", err); process.exit(1);});
// Unhandled promise rejectionprocess.on("unhandledRejection", (reason, promise) => { console.error("Unhandled rejection:", reason);});
// Signalsprocess.on("SIGINT", () => { console.log("Received SIGINT"); process.exit(0);});
process.on("SIGTERM", () => { console.log("Received SIGTERM"); process.exit(0);});Environment Variables π
// Access environment variablesconst port = process.env.PORT || 3000;const dbUrl = process.env.DATABASE_URL;const nodeEnv = process.env.NODE_ENV || "development";
// Set environment variable (runtime)process.env.MY_VAR = "value";
// Load from .env file (requires dotenv package)require("dotenv").config();// Then access: process.env.MY_VAR
// Check if productionconst isProduction = process.env.NODE_ENV === "production";
// Environment-specific configconst config = { development: { apiUrl: "http://localhost:3000", }, production: { apiUrl: "https://api.example.com", },}[process.env.NODE_ENV || "development"];Command Line Arguments π
// Parse arguments manuallyconst args = process.argv.slice(2);const command = args[0];const options = args.slice(1);
// Using minimist (npm package)const minimist = require("minimist");const args = minimist(process.argv.slice(2));// node script.js --port=3000 --debug// β { _: [], port: 3000, debug: true }
// Using yargs (npm package)const yargs = require("yargs");const argv = yargs .option("port", { alias: "p", type: "number", default: 3000, }) .option("debug", { alias: "d", type: "boolean", default: false, }).argv;Error Handling
Try/Catch β οΈ
// Basic try/catchtry { riskyOperation();} catch (error) { console.error("Error:", error.message); console.error("Stack:", error.stack);}
// Try/catch with asynctry { const data = await asyncOperation();} catch (error) { if (error.code === "ENOENT") { console.error("File not found"); } else { console.error("Unknown error:", error); }}
// Multiple catch blocks (not supported, use if/else)try { await operation();} catch (error) { if (error instanceof TypeError) { // Handle TypeError } else if (error instanceof ReferenceError) { // Handle ReferenceError } else { // Handle other errors }}Error Types π¨
// Create custom errorclass CustomError extends Error { constructor(message, code) { super(message); this.name = "CustomError"; this.code = code; }}
throw new CustomError("Something went wrong", "CUSTOM_001");
// Common error typesthrow new Error("Generic error");throw new TypeError("Type error");throw new ReferenceError("Reference error");throw new SyntaxError("Syntax error");throw new RangeError("Range error");
// Error with stack traceconst error = new Error("Error message");console.error(error.stack);Error Handling Patterns π―
// Callback error handlingfunction callbackStyle(callback) { fs.readFile("file.txt", (err, data) => { if (err) { return callback(err); // Early return } callback(null, data); });}
// Promise error handlingfunction promiseStyle() { return fs.promises.readFile("file.txt").catch((err) => { // Handle error throw new Error(`Failed to read file: ${err.message}`); });}
// Async/await error handlingasync function asyncStyle() { try { const data = await fs.promises.readFile("file.txt"); return data; } catch (err) { // Handle error throw new Error(`Failed to read file: ${err.message}`); }}
// Error wrapper utilityfunction asyncHandler(fn) { return (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); };}Package Management
NPM Basics π¦
# Initialize package.jsonnpm initnpm init -y # Skip questions
# Install packagenpm install package-namenpm install package-name --save-dev # Dev dependencynpm install package-name --save-optional # Optional dependencynpm install package-name --save-peer # Peer dependency
# Install specific versionnpm install package-name@1.2.3npm install package-name@^1.2.0 # Compatible versionnpm install package-name@~1.2.0 # Patch versionnpm install package-name@latest # Latest version
# Install from package.jsonnpm install
# Uninstall packagenpm uninstall package-name
# Update packagenpm update package-namenpm update # Update all packages
# List installed packagesnpm listnpm list --depth=0 # Top level onlynpm list package-name # Specific package
# Search packagesnpm search query
# View package infonpm view package-namenpm view package-name versions # All versionsnpm view package-name version # Latest versionPackage.json Scripts π
{ "scripts": { "start": "node index.js", "dev": "node --watch index.js", "test": "jest", "build": "tsc", "lint": "eslint .", "prestart": "echo 'Before start'", "poststart": "echo 'After start'" }}# Run scriptnpm startnpm run devnpm run test
# Run with argumentsnpm run script-name -- --arg value
# Pre and post scripts run automaticallynpm start # Runs prestart β start β poststartNPM Configuration βοΈ
# Set confignpm config set registry https://registry.npmjs.org/npm config set save-exact truenpm config set save-prefix="~"
# Get confignpm config get registry
# List all confignpm config list
# Edit config filenpm config edit
# Remove confignpm config delete key
# Use different registrynpm install --registry https://registry.example.com
# Scoped packagesnpm install @scope/package-namenpm publish --access public # For scoped packagesPNPM (Alternative) π
# Install pnpmnpm install -g pnpm
# Install packages (same as npm)pnpm install package-namepnpm add package-name --dev
# Run scriptspnpm startpnpm run script-name
# Benefits: Faster, disk-efficient, strict dependency resolutionDebugging & Profiling
Node.js Debugger π
# Start debuggernode inspect script.js
# With Chrome DevToolsnode --inspect script.js# Then open chrome://inspect in Chrome
# Break on startnode --inspect-brk script.js
# Debug with VS Code# Add to .vscode/launch.json:{ "type": "node", "request": "launch", "name": "Debug Node.js", "program": "${workspaceFolder}/index.js", "console": "integratedTerminal"}Console Methods π
// Basic loggingconsole.log("Info");console.error("Error");console.warn("Warning");console.info("Info");
// Formatted outputconsole.log("User: %s, Age: %d", "John", 30);console.log("Object: %j", { a: 1 });
// Table outputconsole.table([ { name: "John", age: 30 }, { name: "Jane", age: 25 },]);
// Group logsconsole.group("Group");console.log("Item 1");console.log("Item 2");console.groupEnd();
// Time operationsconsole.time("operation");// ... code ...console.timeEnd("operation");
// Stack traceconsole.trace("Trace message");
// Assertconsole.assert(condition, "Message");Performance Profiling β‘
// Performance timingconst { performance } = require('perf_hooks');
const start = performance.now();// ... code ...const end = performance.now();console.log(`Time: ${end - start}ms`);
// Performance marksperformance.mark('start');// ... code ...performance.mark('end');performance.measure('duration', 'start', 'end');
// Memory usageconst used = process.memoryUsage();console.log({ rss: `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`, heapTotal: `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`, heapUsed: `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`, external: `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`});
// CPU profilingnode --prof script.jsnode --prof-process isolate-*.log > processed.txtBest Practices
β Doβs
// β
Use async/await for async operationsasync function fetchData() { const data = await api.getData(); return data;}
// β
Handle errors properlytry { await operation();} catch (error) { logger.error(error); throw error;}
// β
Use const/let, avoid varconst data = "value";let counter = 0;
// β
Use strict mode("use strict");
// β
Use environment variables for configconst port = process.env.PORT || 3000;
// β
Use streams for large filesfs.createReadStream("large-file.txt") .pipe(transform) .pipe(fs.createWriteStream("output.txt"));
// β
Use process managers in production// PM2, Forever, or systemd
// β
Validate inputif (!input || typeof input !== "string") { throw new Error("Invalid input");}
// β
Use meaningful error messagesthrow new Error("Failed to connect to database: connection timeout");
// β
Clean up resourcesstream.on("end", () => { stream.destroy();});β Donβts
// β Don't use synchronous operations in async contextsconst data = fs.readFileSync("file.txt"); // Blocks event loop
// β Don't ignore errorsfs.readFile("file.txt", (err, data) => { // Missing error handling console.log(data);});
// β Don't use varvar oldStyle = "avoid";
// β Don't block the event loopfor (let i = 0; i < 1000000000; i++) { // Heavy computation blocks event loop}
// β Don't use == (use ===)if (value == null) {} // Use ===
// β Don't mutate function parametersfunction process(data) { data.value = "changed"; // Mutates original}
// β Don't create global variablesglobal.myVar = "bad"; // Avoid
// β Don't use eval()eval('console.log("bad")'); // Security risk
// β Don't ignore promise rejectionspromise.then(() => {}); // Missing .catch()Code Organization π
// β
Separate concernsmodule.exports = { info: (msg) => console.log(`[INFO] ${msg}`), error: (msg) => console.error(`[ERROR] ${msg}`),};
// β
Use modules// config/database.jsmodule.exports = { host: process.env.DB_HOST, port: process.env.DB_PORT,};
// β
Error handling middlewarefunction errorHandler(err, req, res, next) { logger.error(err); res.status(500).json({ error: "Internal server error" });}
// β
Async wrapper for route handlersconst asyncHandler = (fn) => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next);};Common Pitfalls
β οΈ Blocking the Event Loop
// β Bad: Synchronous operation blocks event loopconst data = fs.readFileSync("large-file.txt");
// β
Good: Use async/streamsconst data = await fs.promises.readFile("large-file.txt");// orfs.createReadStream("large-file.txt").pipe(process.stdout);Warning: Synchronous operations block the entire Node.js process. Use async alternatives or streams for I/O operations.
β οΈ Memory Leaks
// β Bad: Event listeners not removedconst emitter = new EventEmitter();emitter.on("data", handler);// Listener stays in memory
// β
Good: Remove listenersemitter.removeListener("data", handler);// oremitter.removeAllListeners();
// β Bad: Closures holding referencesfunction createHandler() { const largeData = new Array(1000000).fill(0); return () => { // largeData stays in memory };}
// β
Good: Clear referencesfunction createHandler() { const largeData = new Array(1000000).fill(0); return () => { // Use data largeData = null; // Clear reference };}β οΈ Unhandled Promise Rejections
// β Bad: Unhandled rejectionasync function fetchData() { const data = await api.getData(); // May reject return data;}fetchData(); // No error handling
// β
Good: Handle errorsasync function fetchData() { try { const data = await api.getData(); return data; } catch (error) { logger.error(error); throw error; }}
// β
Good: Global handlerprocess.on("unhandledRejection", (reason, promise) => { logger.error("Unhandled rejection:", reason);});β οΈ Callback Hell
// β Bad: Nested callbacksfs.readFile("file1.txt", (err, data1) => { fs.readFile("file2.txt", (err, data2) => { fs.readFile("file3.txt", (err, data3) => { // Deep nesting }); });});
// β
Good: Use async/awaitasync function readFiles() { const data1 = await fs.promises.readFile("file1.txt"); const data2 = await fs.promises.readFile("file2.txt"); const data3 = await fs.promises.readFile("file3.txt");}
// β
Good: Use Promise.all for parallelconst [data1, data2, data3] = await Promise.all([ fs.promises.readFile("file1.txt"), fs.promises.readFile("file2.txt"), fs.promises.readFile("file3.txt"),]);β οΈ Error in Callbacks
// β Bad: Throwing in callbackfs.readFile("file.txt", (err, data) => { if (err) throw err; // May not be caught});
// β
Good: Handle in callbackfs.readFile("file.txt", (err, data) => { if (err) { console.error(err); return; } // Process data});
// β
Good: Use promises/asynctry { const data = await fs.promises.readFile("file.txt");} catch (err) { console.error(err);}β οΈ Mixing Callbacks and Promises
// β Bad: Mixing stylesfunction fetchData(callback) { return fetch("api/data") // Returns promise .then((data) => callback(null, data)) // But uses callback .catch(callback);}
// β
Good: Use one style// Promise styleasync function fetchData() { return await fetch("api/data");}
// Callback stylefunction fetchData(callback) { fetch("api/data") .then((data) => callback(null, data)) .catch((err) => callback(err));}