What is Node.js?
Node.js is a runtime that lets you run JavaScript outside the browser — on a server, in a CLI tool, or on your machine. Before Node, JavaScript lived only in web pages. Node set it free.
A Runtime, Not a Language
JavaScript is the language. A runtime is what executes it and provides extra APIs:
- Browser — runs JS with
document,window, and the DOM. - Node.js — runs JS with
fs,http,process, and the file system.
Same language, different toolbox.
Built on V8
Node uses V8, the same fast JavaScript engine that powers Chrome. It compiles your JavaScript to machine code, so Node is quick.
On top of V8, Node adds libuv, a library that handles files, networking, and timers asynchronously.
Non-Blocking I/O
This is Node’s superpower. Instead of waiting for a file read or network call to finish, Node keeps working and handles the result later:
import { readFile } from "node:fs/promises";
const text = await readFile("notes.txt", "utf8");
console.log(text);
While the file loads, Node can serve other requests. That is why it handles many connections with a single thread.
The Event Loop
Node runs your code on one thread. The event loop picks up finished background work (a file read, a timer, a network response) and runs the matching callback. You write async code; the event loop schedules it.
What You Can Build
- Web servers and REST APIs (Express, Fastify, Hono)
- Command-line tools
- Build tools (Vite, esbuild)
- Real-time apps with WebSockets
- Scripts that automate your machine
Node vs the Browser
| Browser | Node.js |
|---|---|
document, window |
process, fs, http |
| Sandboxed, no file access | Full file system access |
| Ships to users | Runs on your server |
fetch built in |
fetch built in (Node 18+) |
Best Practices
- Use the
node:prefix —import fs from "node:fs"is explicit and avoids name clashes. - Prefer promises — Use
node:fs/promisesover callback APIs. - Check your version — Modern Node (20+) supports ESM,
fetch, and top-levelawait.
Common Mistakes
- Thinking Node is a framework — It is a runtime; frameworks run on top of it.
- Blocking the event loop — Heavy synchronous loops freeze every request.
- Assuming browser APIs exist — There is no
documentorwindowin Node. - Ignoring errors — Unhandled promise rejections can crash the process.