Last 30 Days
No notifications
Node.js is a runtime environment that lets you run JavaScript outside the browser. Built on Chrome's V8 engine, it's designed for building scalable, high-performance server applications.
| Feature | Description |
| Non-blocking I/O | Handles thousands of concurrent connections without threads |
| Single-threaded | Uses an event loop instead of creating thread per request |
| V8 Engine | Same fast JavaScript engine as Google Chrome |
| npm ecosystem | Largest package registry in the world (2M+ packages) |
| Full-stack JS | Use JavaScript on both frontend and backend |
Node.js uses a single-threaded event loop to handle concurrency:
┌───────────────────────┐
┌─>│ Timers │ ← setTimeout, setInterval
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O Callbacks │ ← fs, net, etc.
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ Poll │ ← Incoming connections, data
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ Check │ ← setImmediate
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ Close Callbacks │ ← socket.on('close')
│ └──────────┬────────────┘
└─────────────┘| Feature | Browser | Node.js |
| DOM | ✅ | ❌ |
| window object | ✅ | ❌ (has global) |
| File System | ❌ | ✅ |
| HTTP Server | ❌ | ✅ |
| npm modules | Limited | ✅ Full access |
JavaScript was built to run inside a browser. Node.js takes that JavaScript engine (V8) and lets you run JS *outside* the browser — on a server, on your laptop, in a Docker container.
With Node, the same language you use for buttons and forms also runs your API, your database queries, your CLI scripts, even your build tools. One language, top to bottom.
Most server languages (PHP, Java, classic Python) handle one request per thread — 1000 users = 1000 threads = expensive. Node uses a single-threaded event loop: one thread that never blocks. While one request waits on the database, Node serves a hundred others.
The trade-off: if *you* write blocking code (a giant CPU loop), Node freezes for everyone.
node --version # check it's installed
node hello.js # run a script
node # interactive REPL
npm init -y # create a package.json
npm install express # install a libraryA Node project is just a folder with a package.json and any .js files you want.
// server.js
const http = require('http');const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Node!');
});
server.listen(3000, () => console.log('http://localhost:3000'));
node server.js and visit the URL — you've just shipped a web server in 6 lines.
__dirname // absolute path of the current folder
__filename // absolute path of the current file
process.env // environment variables (DATABASE_URL, etc.)
process.argv // command-line args: [node, script, ...flags]
process.cwd() // where the user ran 'node' from
console.log() // same as the browser1. Confusing Node and the browser. No window, no document, no alert(). There *is* process, Buffer, require — none of those exist in the browser.
2. Blocking the event loop. A 5-second for loop freezes every user on your server. Push heavy work to async APIs or worker threads.
3. Hard-coding ports/URLs. Use process.env.PORT so deployment platforms can set it.
4. Forgetting package.json. Without it, your project has no metadata, no scripts, no dependency list.
5. Installing globally for everything. npm install -g is for CLIs. Project deps belong in devDependencies / dependencies.
V8 is what *runs* your JS. It compiles JavaScript to machine code in three stages:
1. Parser → builds an AST (abstract syntax tree) 2. Ignition → fast bytecode interpreter (starts executing immediately) 3. TurboFan → JIT compiles "hot" (frequently-run) functions to optimised machine code
That JIT layer is why Node JS is much faster than naively-interpreted languages like classic Python.
Node itself is small. The async magic comes from libuv, a C library that handles:
epoll (Linux), kqueue (macOS), IOCP (Windows).Your JS code
│
▼
Node.js bindings (C++)
│
▼
libuv (C)
├── Thread pool → fs, crypto, dns, zlib
└── OS async I/O → TCP, UDP, pipesThis is why Node can hold thousands of open connections on a single thread.
npm install express # add a runtime dep
npm install --save-dev jest # add a dev-only dep
npm install -g vercel # global CLI tool
npm run dev # run a script from package.json
npm outdated # show updates
npm audit fix # patch known vulnsnode_modules/ holds all installed packages — *never* commit it. package-lock.json *should* be committed; it pins exact versions for reproducible installs.
The Node ecosystem has two module systems:
// CommonJS (older, default in many projects)
const fs = require('fs');
module.exports = { hello };// ES Modules (modern, browser-compatible)
import fs from 'node:fs';
export function hello() {}
Flip with "type": "module" in package.json (or use .mjs/.cjs extensions).
Excellent for:
Real CPU work? Node has worker_threads:
const { Worker } = require('node:worker_threads');
new Worker('./heavy-job.js');Need multiple processes to use all CPU cores? Use cluster or — preferably — a process manager like PM2 or run multiple containers behind a load balancer.
Node releases a new major every 6 months; even-numbered ones become LTS (Long-Term Support, ~30 months). Stick to current LTS in production. Use nvm (or Volta / fnm) to switch versions per project — never install Node globally with the OS package manager.
1. node -v, run a one-liner script that prints process.argv.
2. Build the 6-line HTTP server above; add a JSON endpoint at /api/time that returns the current time.
3. Read package.json from disk inside your script, parse it, log the dependency list.
4. Add an npm run dev script that uses nodemon to auto-restart on changes.