What is Node.js?
Node.js is a runtime for executing JavaScript on the server, built on Chrome's V8 engine. It uses an event-driven, non-blocking I/O model ideal for I/O-heavy applications.
// Minimal HTTP server
import http from 'http';
const server = http.createServer((req, res) => {
res.end('Hello Node');
});
server.listen(3000);Event loop basics
Node.js is single-threaded for JavaScript but handles I/O using the event loop and libuv thread pool. Tasks are queued as microtasks (Promises) and macrotasks (timers, I/O).
setTimeout(() => console.log('timer'), 0);
Promise.resolve().then(() => console.log('microtask'));
console.log('sync'); // sync → microtask → macrotaskESM vs CommonJS
CommonJS uses require/module.exports; ESM uses import/export. Prefer ESM in modern Node with "type": "module".
// ESM
import fs from 'fs/promises';
export function read(path) { return fs.readFile(path, 'utf8'); }Express basics
Express is a minimal web framework for routing and middleware.
import express from 'express';
const app = express();
app.use(express.json());
app.get('/health', (_req, res) => res.json({ ok: true }));
app.post('/users', (req, res) => res.status(201).json(req.body));
app.listen(3000);What is middleware?
Middleware are functions that run before route handlers. They can parse bodies, handle auth, log requests, etc.
app.use((req, _res, next) => { console.log(req.method, req.url); next(); });Streams
Streams process data in chunks (readable, writable, transform). They reduce memory usage for large files.
import { createReadStream } from 'fs';
createReadStream('big.txt')
.on('data', chunk => console.log('chunk', chunk.length))
.on('end', () => console.log('done'));Environment variables
Use process.env for secrets/config. Load via dotenv or platform env.
import 'dotenv/config'; const dbUrl = process.env.DATABASE_URL ?? 'sqlite://dev.db';
Error handling
Handle async errors with try/catch and centralized error middleware.
app.use((err, _req, res, _next) => {
console.error(err);
res.status(500).json({ error: 'Internal Server Error' });
});Cluster and scaling
Use cluster or PM2 to spawn workers across CPU cores, and load balancers (NGINX) to distribute traffic.
Worker Threads vs Cluster
Workers run JS on separate threads for CPU-bound tasks; Cluster forks processes to use multiple cores for I/O-bound servers.
Child processes
Use child_process to spawn external commands or fork Node instances; communicate via IPC channels.
EventEmitter
Publish/subscribe model in Node core; manage listeners and handle memory leaks with removeListener and once.
process.nextTick vs setImmediate
nextTick queues microtasks before I/O; setImmediate runs after I/O callbacks; use carefully to avoid starvation.
Debugging Node
Use --inspect with Chrome DevTools or VSCode; add breakpoints, profile CPU/memory, and analyze heap snapshots.