Express.js Fundamentals

Difficulty: Beginner

Question

What is Express.js and why is it the most popular Node.js framework? Show the basic setup and key features.

Answer

Express.js is a minimal, unopinionated web framework for Node.js that provides a thin layer of fundamental features on top of the http module. It simplifies routing, middleware handling, request/response processing, and template rendering.

Express enhances the native req and res objects with helper methods like req.params, req.query, req.body (with middleware), res.json(), res.status(), res.send(), and res.redirect(). These save significant boilerplate compared to the raw http module.

The framework follows a middleware-based architecture where each request passes through a pipeline of functions. This makes it easy to add features like body parsing, authentication, logging, and error handling as composable layers.

Express Router allows you to organize routes into modular groups. Each router acts as a mini-application with its own middleware and routes, which can be mounted at a specific path prefix. This is how large applications stay organized.

Code examples

Basic Express Application Setup

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

// Built-in middleware
app.use(express.json());               // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse form data
app.use(express.static('public'));      // Serve static files

// Route handlers
app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.get('/api/users', (req, res) => {
  // req.query contains URL parameters: /api/users?page=2&limit=10
  const { page = 1, limit = 10 } = req.query;
  res.json({
    page: Number(page),
    limit: Number(limit),
    users: [{ id: 1, name: 'Alice' }]
  });
});

app.post('/api/users', (req, res) => {
  // req.body available thanks to express.json()
  const { name, email } = req.body;
  res.status(201).json({ id: 1, name, email });
});

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

express.json() parses request bodies. Route methods match HTTP verbs. res.json() automatically sets Content-Type and stringifies.

Express Router for Modular Routes

// routes/users.js
const express = require('express');
const router = express.Router();

// Routes are relative to the mount point
router.get('/', (req, res) => {
  res.json({ users: [] });
});

router.get('/:id', (req, res) => {
  res.json({ user: { id: req.params.id } });
});

router.post('/', (req, res) => {
  res.status(201).json({ user: req.body });
});

router.put('/:id', (req, res) => {
  res.json({ updated: req.params.id });
});

router.delete('/:id', (req, res) => {
  res.status(204).end();
});

module.exports = router;

// index.js
const userRoutes = require('./routes/users');
const productRoutes = require('./routes/products');

app.use('/api/users', userRoutes);
app.use('/api/products', productRoutes);

Routers group related endpoints. Each router only defines paths relative to its mount point. This is the standard pattern for organizing Express apps.

Response Helper Methods

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

app.get('/examples', (req, res) => {
  // Send JSON
  res.json({ key: 'value' });

  // Set status + JSON
  res.status(404).json({ error: 'Not found' });

  // Send text/HTML
  res.send('<h1>Hello</h1>');

  // Send file
  res.sendFile('/path/to/file.pdf');

  // Redirect
  res.redirect(301, '/new-location');

  // Set custom headers
  res.set('X-Custom-Header', 'value');

  // Send status only
  res.sendStatus(204); // No Content

  // Download
  res.download('/path/to/file.pdf', 'report.pdf');
});

// Chaining
app.get('/chain', (req, res) => {
  res
    .status(200)
    .set('Cache-Control', 'public, max-age=3600')
    .json({ cached: true });
});

Express provides many response helpers. res.json() handles serialization. res.status() is chainable. res.sendFile() handles streaming and headers automatically.

Key points

Concepts covered

Express, app.use, Router, Request, Response