Ad – 728Γ—90
⚑ Frameworks

Node.js – Running JavaScript on the Server

Node.js is a JavaScript runtime built on Chrome's V8 engine that lets you run JavaScript outside the browser β€” on servers, CLIs, scripts, and desktop apps. Its event-driven, non-blocking I/O model makes it exceptionally efficient for I/O-heavy workloads like APIs, real-time apps, and microservices.

⏱️ 23 min read 🎯 Advanced πŸ“… Updated 2026

What Is Node.js?

Ryan Dahl created Node.js in 2009, embedding the V8 JavaScript engine in a C++ program that adds APIs for file system access, networking, processes, and more. Key characteristics:

  • Single-threaded event loop β€” one thread handles all I/O via callbacks/Promises, avoiding thread management complexity.
  • Non-blocking I/O β€” operations like reading files or querying databases don't block the thread; the loop continues processing while waiting for I/O.
  • Same language everywhere β€” JavaScript on client and server reduces context switching and enables code sharing.
  • npm ecosystem β€” over 2 million packages available.

Installing Node.js and Running Code

JavaScript
// Download from nodejs.org or use a version manager:
// nvm install 20   (Node Version Manager β€” recommended)
// nvm use 20

// Check versions
// $ node --version   β†’ v20.x.x
// $ npm --version    β†’ 10.x.x

// REPL (Read-Eval-Print Loop) β€” interactive shell
// $ node
// > 2 + 2
// 4
// > 'hello'.toUpperCase()
// 'HELLO'
// > .exit

// Run a file
// $ node app.js

// Basic Node.js script β€” hello.js
console.log('Hello from Node.js!');
console.log('Node version:', process.version);
console.log('Platform:', process.platform);   // 'linux', 'darwin', 'win32'
console.log('Working dir:', process.cwd());

// process.argv β€” command-line arguments
// $ node greet.js Alice
const name = process.argv[2] || 'World';
console.log(`Hello, ${name}!`);
β–Ά Output
Hello from Node.js!
Node version: v20.11.0
Platform: linux
Working dir: /home/user/my-project

Node.js Global Objects

JavaScript
// __dirname β€” absolute path of current file's directory
console.log(__dirname);  // /home/user/project/src

// __filename β€” absolute path of current file
console.log(__filename); // /home/user/project/src/app.js

// process β€” information about the running Node process
process.env.NODE_ENV = 'development';     // set env variable
console.log(process.env.PORT || 3000);    // read env variable
process.exit(0);                          // exit with code 0 (success)

// Buffer β€” handle binary data
const buf = Buffer.from('Hello');
console.log(buf);           // <Buffer 48 65 6c 6c 6f>
console.log(buf.toString()); // "Hello"

// global β€” equivalent of window in browsers (rarely used directly)
global.myConfig = { debug: true };

// setTimeout, setInterval, clearTimeout, clearInterval β€” same as browser
const timer = setTimeout(() => console.log('fired!'), 1000);
clearTimeout(timer);

Core Built-in Modules

JavaScript
// No npm install needed β€” built into Node.js

// fs β€” File System
const fs = require('fs');
// Or with ES modules: import fs from 'fs';

// Read file (async with callback)
fs.readFile('data.txt', 'utf8', (err, content) => {
  if (err) throw err;
  console.log(content);
});

// Read file (Promise-based β€” preferred)
const fsPromises = require('fs/promises');
const content = await fsPromises.readFile('data.txt', 'utf8');
console.log(content);

// Write file
await fsPromises.writeFile('output.txt', 'Hello Node!');

// path β€” cross-platform file path utilities
const path = require('path');
const filePath = path.join(__dirname, 'data', 'users.json');
console.log(path.basename(filePath)); // "users.json"
console.log(path.extname(filePath));  // ".json"
console.log(path.dirname(filePath));  // "/home/.../data"

// os β€” operating system info
const os = require('os');
console.log(os.platform());  // "linux"
console.log(os.cpus().length); // number of CPU cores
console.log(os.freemem());   // free memory in bytes
console.log(os.homedir());   // "/home/user"

npm Basics

JavaScript
// Initialize a project β€” creates package.json
// $ npm init -y

// Install a package (saved to dependencies)
// $ npm install express

// Install a dev dependency (only for development/build)
// $ npm install --save-dev nodemon

// Install globally (CLI tools)
// $ npm install -g typescript

// Remove a package
// $ npm uninstall lodash

// package.json structure
// {
//   "name": "my-app",
//   "version": "1.0.0",
//   "main": "index.js",
//   "scripts": {
//     "start": "node index.js",
//     "dev": "nodemon index.js",
//     "test": "jest"
//   },
//   "dependencies": { "express": "^4.18.0" },
//   "devDependencies": { "nodemon": "^3.0.0" }
// }

// Run scripts
// $ npm run dev
// $ npm start      (shortcut β€” no "run" needed)
// $ npm test       (shortcut β€” no "run" needed)

// npx β€” run a package without installing it globally
// $ npx create-react-app my-app
// $ npx nodemon index.js
ℹ️
Commit package.json but not node_modules

Always add node_modules/ to your .gitignore. The package.json and package-lock.json files are sufficient for any developer to recreate the exact dependency tree by running npm install.

Built-in HTTP Server

JavaScript
const http = require('http');
const fs   = require('fs/promises');
const path = require('path');

const server = http.createServer(async (req, res) => {
  const url = req.url;
  const method = req.method;

  console.log(`${method} ${url}`);

  if (url === '/' && method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>Hello from Node.js!</h1>');

  } else if (url === '/api/users' && method === 'GET') {
    const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(users));

  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not Found' }));
  }
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

Express.js – The Standard Node Web Framework

Express adds routing, middleware, and a clean request/response API on top of Node's built-in http:

JavaScript
// npm install express
const express = require('express');
const app = express();

// Built-in middleware β€” parse JSON request bodies
app.use(express.json());
// Serve static files from /public folder
app.use(express.static('public'));

// Routes
app.get('/', (req, res) => {
  res.send('<h1>Welcome to Express!</h1>');
});

app.get('/api/users', async (req, res) => {
  try {
    const users = await getUsersFromDB();
    res.json(users);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Route parameters
app.get('/api/users/:id', (req, res) => {
  const { id } = req.params;
  res.json({ id, name: 'Alice' });
});

// POST with body
app.post('/api/users', (req, res) => {
  const { name, email } = req.body;
  if (!name || !email) {
    return res.status(400).json({ error: 'name and email required' });
  }
  const newUser = { id: Date.now(), name, email };
  res.status(201).json(newUser);
});

// Custom middleware β€” runs before route handlers
app.use((req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
  next(); // pass to next middleware or route
});

app.listen(3000, () => console.log('Express server on port 3000'));

Browser JS vs Node.js

FeatureBrowser JavaScriptNode.js
Runtime environmentBrowser tabServer / CLI / scripts
Global objectwindowglobal
DOM APIYes (document, window)No (no browser)
File systemNo (sandboxed)Yes (fs module)
ModulesES Modules nativelyCommonJS (require) or ESM
Package managerCDN / importmapnpm / yarn / pnpm
HTTPFetch API (client)Built-in http / Express (server)
Use casesUI, interactivityAPIs, CLIs, build tools, scripts
⚠️
Node.js is not great for CPU-intensive work

Node's single-threaded model excels at I/O-bound tasks (API calls, DB queries, file reads) but struggles with CPU-heavy work (image processing, video encoding, complex math). For CPU tasks, use Worker Threads, spawn a child process, or delegate to a language better suited to computation (Python, Rust, Go).

πŸ‹οΈ Practical Exercise

Build a simple REST API with Express:

  1. GET /api/notes β€” return all notes (store in an in-memory array).
  2. GET /api/notes/:id β€” return a single note by ID (404 if not found).
  3. POST /api/notes β€” create a note from { title, content } body; assign an auto-increment ID.
  4. DELETE /api/notes/:id β€” remove a note; 204 on success, 404 if missing.
  5. Test with curl or a browser extension like Thunder Client.

πŸ”₯ Challenge Exercise

Build a real-time chat server using Node.js built-in http and the ws npm package for WebSockets. The server: broadcasts messages from any client to all connected clients; prepends a random username to each message; stores the last 10 messages in memory and sends them to new connections. The client: a plain HTML page with a textarea and send button that connects via new WebSocket('ws://localhost:3000'). Open two browser tabs to test real-time updates.

Summary

πŸ“‹ Summary

  • Node.js runs JavaScript on the server using Chrome's V8 engine.
  • Event-driven, non-blocking I/O makes Node efficient for API servers and real-time apps.
  • Global objects: process, __dirname, __filename, Buffer.
  • Core modules: fs (file I/O), path (path utilities), http (server), os (system info).
  • npm manages packages; package.json declares dependencies and scripts.
  • Express.js adds routing, middleware, and a clean API on top of Node's http.
  • Use npx to run CLI tools without global installation.

Interview Questions

  • What is the event loop in Node.js and how does non-blocking I/O work?
  • What is the difference between dependencies and devDependencies in package.json?
  • What is middleware in Express? Give an example of a custom middleware.
  • What is the difference between npm install and npx?
  • When is Node.js a poor choice for a task?

Frequently Asked Questions

What is the difference between CommonJS and ES Modules in Node.js? +

CommonJS (require() / module.exports) is Node's original module system β€” synchronous, loaded at runtime. ES Modules (import / export) are the browser-standard, asynchronous module system added to Node in v12+. To use ESM in Node, add "type": "module" to package.json or use .mjs file extensions. Modern projects prefer ESM for consistency with browser code.

How does Node.js handle multiple requests on a single thread? +

Node uses an event loop backed by libuv (a C library). When an I/O operation (database query, file read, HTTP request) is initiated, Node delegates it to the OS/thread pool and continues processing other events. When the I/O completes, a callback is placed in the event queue and the event loop picks it up on the next tick. This means Node can handle thousands of concurrent connections without spawning thousands of threads.

Should I use Express or a newer framework like Fastify or Hono? +

Express has the largest ecosystem and most tutorials β€” ideal for learning and legacy projects. Fastify is 2–4x faster and has schema-based validation built in. Hono is ultra-lightweight and edge-runtime compatible (Cloudflare Workers, Deno Deploy). For a new production API in 2026, Fastify or Hono are excellent choices; Express remains perfectly valid for most use cases.

Ad – 336Γ—280