Notifications

No notifications

/Phase 1

What is Node.js?

Node.js — JavaScript on the Server

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.

Why Node.js?

FeatureDescription
Non-blocking I/OHandles thousands of concurrent connections without threads
Single-threadedUses an event loop instead of creating thread per request
V8 EngineSame fast JavaScript engine as Google Chrome
npm ecosystemLargest package registry in the world (2M+ packages)
Full-stack JSUse JavaScript on both frontend and backend

The Event Loop

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')
│  └──────────┬────────────┘
└─────────────┘

Node.js vs Browser

FeatureBrowserNode.js
DOM
window object❌ (has global)
File System
HTTP Server
npm modulesLimited✅ Full access

On this page

Detailed Theory

What Node.js Actually Is

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.

Why Node Is Different

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.

Installing & Running Node

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 library

A Node project is just a folder with a package.json and any .js files you want.

Your First Server

// 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.

Globals You'll See Daily

__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 browser

Beginner Mistakes to Skip

1. 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.

Intermediate: V8, the JavaScript Engine

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.

Intermediate: libuv & the Event Loop

Node itself is small. The async magic comes from libuv, a C library that handles:

  • A thread pool (default 4 threads) for things the OS can't do async natively — file I/O, DNS, crypto, zlib.
  • OS-level async I/O for networking — 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, pipes

This is why Node can hold thousands of open connections on a single thread.

Intermediate: npm — The Package Manager

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 vulns

node_modules/ holds all installed packages — *never* commit it. package-lock.json *should* be committed; it pins exact versions for reproducible installs.

Intermediate: ESM vs CommonJS

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).

Advanced: When Node Shines (and Doesn't)

Excellent for:

  • REST/GraphQL APIs, BFF layers
  • Real-time apps (chat, multiplayer, live dashboards via WebSockets)
  • Streaming uploads/downloads
  • Serverless functions (cold-starts in tens of ms)
  • CLI tools and build pipelines
A poor fit for:
  • CPU-bound work (image processing, ML training, scientific compute)
  • Anything that benefits from real multi-threaded shared memory (use Worker Threads if you must)

Advanced: Worker Threads & Cluster

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.

Advanced: Versions & LTS

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.

Practice Path

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.