Complete Learning Guide

Master Node.js
From Zero to Expert

Learn what Node.js is, how it works under the hood, and how to build real web applications — step by step, with clear explanations.

5
Chapters
20+
Code Examples
15
Quiz Questions
🟢

What is Node.js?

Node.js is a runtime environment. It lets you run JavaScript code outside of a browser. Before Node.js, JavaScript only worked inside web browsers. Now, you can use JavaScript to build servers, tools, and full applications.

Ryan Dahl created Node.js in 2009. He built it on Google's V8 JavaScript engine. The V8 engine compiles JavaScript into fast machine code. This makes Node.js very fast and efficient.

Fast & Lightweight
Node.js uses the V8 engine. It compiles JavaScript directly to machine code. Your code runs very fast as a result.
🔄
Non-Blocking I/O
Node.js does not wait for one task to finish before starting another. It handles many tasks at the same time. This is called asynchronous programming.
📦
npm Ecosystem
Node.js comes with npm — the Node Package Manager. npm gives you access to over 2 million free packages. You can add powerful features with just one command.
🌍
One Language, Full Stack
You can use JavaScript for both the frontend and the backend. You do not need to learn two languages. This saves time and reduces complexity.

Where is Node.js Used?

Many large companies use Node.js in production. Here are some major examples:

Company What they use Node.js for Scale
NetflixStreaming backend, fast startup time300M+ users
LinkedInMobile backend, replaced Ruby on Rails10x fewer servers needed
UberReal-time trip dispatch systemMillions of requests/second
NASAEVA spacewalk data systemCritical real-time data

Node.js vs Traditional Server Approaches

⚙️ Traditional Server (PHP, Java)
  • Creates a new thread for each request
  • Waits (blocks) while reading files or database
  • Uses more memory per connection
  • Harder to scale under heavy load
⚡ Node.js
  • Uses a single thread for all requests
  • Continues while waiting — never blocks
  • Very low memory usage per connection
  • Scales easily to handle millions of requests
⚙️

How Node.js Works

Node.js has three key components that work together. Understanding these three parts will help you write better Node.js code.

🏎️
V8 Engine
Google built V8 for Chrome. It converts JavaScript into machine code instantly. Node.js uses V8 to run your JavaScript on the server.
🔁
Event Loop
The event loop is the heart of Node.js. It keeps running, checking if any tasks are ready. It processes tasks one at a time without blocking.
🧵
libuv
libuv is a C library that handles asynchronous I/O. It manages the thread pool for heavy tasks like file reading, so Node.js stays free.

The Event Loop — Step by Step

Here is what happens when a request arrives in Node.js:

1
Request Arrives
A user sends a request. Node.js receives it and adds it to the Call Stack.
2
Offload Slow Tasks
If the task is slow (like reading a file), Node.js gives it to libuv. The main thread is now free to handle other requests.
3
Task Completes
When the slow task finishes, libuv puts the result in the Callback Queue.
4
Event Loop Picks It Up
The Event Loop checks the Callback Queue. When the Call Stack is empty, it picks up the callback and runs it.
5
Response Sent
Node.js sends the response back to the user. The loop continues for the next request.

Synchronous vs Asynchronous Code

This is the most important concept in Node.js. Here is the difference:

sync-vs-async.js
// ❌ SYNCHRONOUS — Blocks everything (avoid this)
const fs = require('fs');

const data = fs.readFileSync('file.txt'); // WAITS here
console.log(data);                         // Only runs after file is read
console.log('This waits too...');          // Everything is blocked

// ✅ ASYNCHRONOUS — Never blocks (use this)
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);                       // Runs when file is ready
});
console.log('This runs immediately!');     // Does not wait

Promises and Async/Await (Modern Approach)

Modern Node.js uses async/await. It makes asynchronous code look like synchronous code. It is cleaner and easier to read.

async-await.js
const fs = require('fs').promises;

// Using async/await — clean and readable
async function readMyFile() {
  try {
    const data = await fs.readFile('file.txt', 'utf8');
    console.log(data);
  } catch (err) {
    console.log('Error:', err.message);
  }
}

readMyFile();
💡 Key Takeaway

Node.js runs on a single thread, but it never sits idle. The Event Loop keeps it busy. While one task waits for data, Node.js processes other requests. This is why it handles millions of connections with low memory.

🏗️

Build a Web Application

Let's build a complete web application with Node.js. We will use only built-in modules — no third-party libraries. The app will serve web pages and handle API requests.

📁 Project Structure

my-app/ → server.js, data.json, public/ (index.html, app.js, style.css)

Step 1 — Install Node.js

Go to nodejs.org and download the LTS version. LTS stands for Long Term Support. It is the most stable version. After installing, check if it works:

terminal
# Check Node.js version
node --version    # Should print: v20.x.x or higher
npm --version     # Should print: 10.x.x or higher

# Create your project folder
mkdir my-app
cd my-app

Step 2 — Create the Server

This server does three things. It serves static files. It handles API routes. It sends proper HTTP responses.

server.js
const http  = require('http');
const fs    = require('fs');
const path  = require('path');
const url   = require('url');

// In-memory data store (replaces a database)
let tasks = [
  { id: 1, title: 'Learn Node.js', done: false },
  { id: 2, title: 'Build a server', done: false }
];

// Map file extensions to MIME types
const mimeTypes = {
  '.html': 'text/html',
  '.css':  'text/css',
  '.js':   'text/javascript',
  '.json': 'application/json'
};

// Helper: send a JSON response
function sendJSON(res, status, data) {
  res.writeHead(status, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(data));
}

// Helper: serve static files from /public
function serveStatic(req, res) {
  let filePath = path.join(__dirname, 'public',
    req.url === '/' ? 'index.html' : req.url);

  fs.readFile(filePath, (err, data) => {
    if (err) {
      res.writeHead(404);
      res.end('Not Found');
      return;
    }
    const ext = path.extname(filePath);
    res.writeHead(200, { 'Content-Type': mimeTypes[ext] || 'text/plain' });
    res.end(data);
  });
}

// Main request handler
const server = http.createServer((req, res) => {
  const parsed = url.parse(req.url, true);
  const pathname = parsed.pathname;

  // API Routes
  if (pathname === '/api/tasks' && req.method === 'GET') {
    return sendJSON(res, 200, { success: true, tasks });
  }

  if (pathname === '/api/tasks' && req.method === 'POST') {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      const { title } = JSON.parse(body);
      const newTask = { id: Date.now(), title, done: false };
      tasks.push(newTask);
      sendJSON(res, 201, { success: true, task: newTask });
    });
    return;
  }

  // Serve static files for everything else
  serveStatic(req, res);
});

server.listen(3000, () => {
  console.log('✅ Server running → http://localhost:3000');
});

Step 3 — Create the Frontend

The frontend talks to our server using fetch(). It displays tasks and lets users add new ones. No framework is needed.

public/app.js
// Load tasks when the page opens
async function loadTasks() {
  const res  = await fetch('/api/tasks');
  const json = await res.json();

  const list = document.getElementById('task-list');
  list.innerHTML = json.tasks
    .map(t => `<li>${t.title}</li>`)
    .join('');
}

// Add a new task
async function addTask(title) {
  await fetch('/api/tasks', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ title })
  });
  loadTasks(); // Refresh the list
}

document.getElementById('add-btn')
  .addEventListener('click', () => {
    const input = document.getElementById('task-input');
    if (input.value.trim()) {
      addTask(input.value.trim());
      input.value = '';
    }
  });

loadTasks(); // Run on page load

Step 4 — Run Your Application

terminal
node server.js
# Output: ✅ Server running → http://localhost:3000
# Open your browser and go to http://localhost:3000
🎉 What You Just Built

You built a working web server in pure Node.js. It serves HTML pages, handles GET and POST requests, stores data in memory, and parses JSON — all without any libraries.

Built-in Modules You Used

Module Purpose Key Methods
httpCreate HTTP servers and clientscreateServer, listen
fsRead and write files on diskreadFile, writeFile, readFileSync
pathWork with file and folder pathsjoin, extname, basename
urlParse URLs and query stringsparse, format
cryptoGenerate hashes, tokens, UUIDscreateHash, randomUUID
📋

Node.js Cheat Sheet

Keep these patterns handy. They cover 90% of what you need in real Node.js applications.

🌐 Create HTTP Server
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end('<h1>Hello World</h1>');
});
server.listen(3000);
📁 Read / Write Files
const fs = require('fs').promises;

// Read
const data = await fs.readFile('file.txt', 'utf8');

// Write
await fs.writeFile('out.txt', 'Hello!');
📦 Parse Request Body
function getBody(req) {
  return new Promise((resolve) => {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => resolve(JSON.parse(body)));
  });
}
const data = await getBody(req);
🔗 Parse URL & Query Params
const url = require('url');

// req.url = '/search?q=nodejs&page=2'
const parsed = url.parse(req.url, true);
parsed.pathname;  // '/search'
parsed.query.q;    // 'nodejs'
parsed.query.page;  // '2'
🔒 Hash a Password
const crypto = require('crypto');

function hashPassword(password) {
  return crypto
    .createHash('sha256')
    .update(password)
    .digest('hex');
}
⏱️ Simple Router Pattern
const routes = {
  'GET /':           handleHome,
  'GET /api/users':  getUsers,
  'POST /api/users': createUser,
};

const key = `${req.method} ${req.url}`;
const handler = routes[key];
handler ? handler(req, res) : send404(res);
📊 Read/Write JSON Data
const fs = require('fs').promises;

// Read JSON file as object
const raw  = await fs.readFile('data.json', 'utf8');
const data = JSON.parse(raw);

// Save object as JSON file
await fs.writeFile('data.json', JSON.stringify(data, null, 2));
🌍 Set CORS Headers
function setCORS(res) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods',
    'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers',
    'Content-Type');
}
No Libraries Needed Built-in Modules Production Ready async/await Event Loop V8 Engine

Node.js Quiz