Python Java C++ HTML CSS Bootstrap JavaScript jQuery AngularJS React Node.js TypeScript Django NumPy Pandas Matplotlib Seaborn Machine Learning Deep Learning Decipher XML

Introduction

Node.js is a JavaScript runtime built on Chrome's V8 engine. It enables server-side execution of JavaScript and is optimized for building scalable, networked applications.

Why Node.js works well for modern backends:

  • Event-driven, non-blocking I/O for high concurrency
  • Single-threaded event loop with async tasks offloaded to the libuv thread pool
  • Vast ecosystem via npm for frameworks, tooling, and integrations
Node.js is asynchronous and event-driven, making it ideal for I/O-heavy applications like APIs, real-time apps, and streaming services.

Installation & Setup

# Install Node.js
https://nodejs.org/en/download/

# Verify installation
node -v
npm -v
      

Use the LTS version for stability in production. For multiple projects, prefer a version manager like nvm so you can switch Node versions easily.

Typical project setup includes:

  • npm init to create package.json
  • Scripts for dev, build, and test
  • Environment configs using .env
# Initialize a project
npm init -y

# Add a dev script
// package.json
// "scripts": { "dev": "node index.js" }

Modules in Node.js

const fs = require('fs'); // built-in module
const myModule = require('./myModule'); // custom module

Node.js supports CommonJS (require/module.exports) and ES modules (import/export). ES modules are enabled via "type": "module" in package.json or using .mjs.

Advanced module ideas:

  • Module caching: a module is executed once and then cached
  • Built-ins like fs, path, http, crypto
  • Named exports vs default exports for better tooling
// ES module
import path from 'path';
export function slugify(text) { return text.toLowerCase().replace(/\s+/g, '-'); }

NPM (Node Package Manager)

# Initialize project
npm init -y

# Install package
npm install express

# Install globally
npm install -g nodemon

NPM manages dependencies, scripts, and versioning. It uses package.json for metadata and package-lock.json for deterministic installs.

Useful npm concepts:

  • Semver ranges: ^ and ~ control updates
  • Dev dependencies vs production dependencies
  • Scripts for linting, testing, and builds
# Add a script and run it
npm pkg set scripts.test="node test.js"
npm run test

HTTP Module & Server

const http = require('http');
const server = http.createServer((req,res)=>{
  res.writeHead(200, {'Content-Type':'text/plain'});
  res.end('Hello Node.js!');
});
server.listen(3000, ()=>console.log('Server running on port 3000'));

The built-in http module provides low-level control over requests and responses. It is fast but requires manual routing and parsing.

Advanced usage:

  • Parse URLs and query strings
  • Handle streams for large payloads
  • Set headers and status codes explicitly
const { URL } = require('url');
const server = http.createServer((req,res)=>{
  const url = new URL(req.url, `http://${req.headers.host}`);
  res.writeHead(200, {'Content-Type':'application/json'});
  res.end(JSON.stringify({ path: url.pathname }));
});

Node.js allows creating servers without external libraries, but frameworks like Express simplify common tasks.

Express.js Basics

const express = require('express');
const app = express();

app.get('/', (req,res)=> res.send('Hello Express!'));

app.listen(3000, ()=> console.log('Server running'));

Express is a minimal web framework that adds routing, middleware support, and request/response helpers.

Core ideas:

  • Middleware pipeline: app.use() runs in order
  • Request/response helpers like res.json() and res.status()
  • Composable routers for modular APIs
const router = express.Router();
router.get('/status', (req,res)=> res.json({ ok: true }));
app.use('/api', router);

Routing

app.get('/about', (req,res)=> res.send('About Page'));
app.post('/login', (req,res)=> res.send('Login'));

Routing maps HTTP methods and paths to handler functions. You can access params, query strings, and request bodies.

Advanced routing features:

  • Route parameters: /users/:id
  • Query strings via req.query
  • Chained handlers for validation and auth
app.get('/users/:id', (req,res)=>{
  res.json({ id: req.params.id, q: req.query.q });
});

Middleware

app.use(express.json()); // parse JSON body
app.use((req,res,next)=>{
  console.log(req.url);
  next();
});

Middleware functions run in sequence and can modify req, res, or terminate the request.

Key middleware patterns:

  • Error handlers have 4 args: (err, req, res, next)
  • Authentication and rate limiting
  • Static file hosting via express.static
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});

File System (fs)

const fs = require('fs');

// Read file
fs.readFile('data.txt','utf-8',(err,data)=>console.log(data));

// Write file
fs.writeFile('output.txt','Hello Node',err=>{if(err)console.log(err)});

The fs module supports async, sync, and promise-based APIs. Prefer async or promise-based methods for performance.

Advanced usage:

  • Streams for large files
  • fs.promises with async/await
  • Path safety with path.join
const fsPromises = require('fs').promises;
const path = require('path');
const filePath = path.join(__dirname, 'data.txt');
const data = await fsPromises.readFile(filePath, 'utf-8');

Events & EventEmitter

const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.on('message',(msg)=>console.log(msg));
emitter.emit('message','Hello Events!');

EventEmitter is the core pattern behind many Node APIs (streams, HTTP, etc.). It enables decoupled, async communication.

Advanced event patterns:

  • once for single-use events
  • Remove listeners to prevent memory leaks
  • Use error event for error handling
emitter.once('ready', () => console.log('Ready once'));
emitter.on('error', err => console.error(err));

Asynchronous Programming

const fs = require('fs');

// Callback
fs.readFile('file.txt','utf-8',(err,data)=>console.log(data));

// Promises
const fsPromises = fs.promises;
fsPromises.readFile('file.txt','utf-8').then(console.log);

// Async/Await
async function readFile(){
  const data = await fsPromises.readFile('file.txt','utf-8');
  console.log(data);
}
readFile();

Async code in Node runs on the event loop. Use promises and async/await to keep code readable and handle errors consistently.

Common async patterns:

  • Parallel tasks with Promise.all
  • Sequential tasks with await
  • Try/catch for async error handling
try {
  const [a, b] = await Promise.all([taskA(), taskB()]);
  console.log(a, b);
} catch (err) {
  console.error(err);
}

Database Integration

// Using MongoDB with Mongoose
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/testdb');

const UserSchema = new mongoose.Schema({name:String,age:Number});
const User = mongoose.model('User',UserSchema);

const user = new User({name:'Alice',age:25});
user.save();

Node.js can connect with SQL or NoSQL databases via drivers or ORMs/ODMs. Mongoose adds schema modeling and validation on top of MongoDB.

Advanced database considerations:

  • Connection pooling for performance
  • Indexes for query speed
  • Validation and schema design to avoid inconsistent data
const userSchema = new mongoose.Schema(
  { name: { type: String, required: true }, age: { type: Number, min: 0 } },
  { timestamps: true }
);

Building REST APIs

app.get('/users', async (req,res)=>{
  const users = await User.find();
  res.json(users);
});

app.post('/users', async (req,res)=>{
  const newUser = await User.create(req.body);
  res.json(newUser);
});

REST APIs use standard HTTP methods and status codes to represent CRUD operations. Consistent responses and error handling are critical.

API best practices:

  • Return proper status codes (201, 400, 404)
  • Validate input before writing to the database
  • Implement pagination and filtering for large datasets
app.post('/users', async (req,res)=>{
  const user = await User.create(req.body);
  res.status(201).json(user);
});