Back to all posts

Express.js a complete Guide


Getting Started with Express.js

  1. What is Express.js?
  2. Installing Express.js
  3. Adding Middleware & How It Works
    • Understanding next()
    • The response object (res)
  4. Handling Different Routes
  5. Assignment: Building a Simple Book API

Advanced Express.js Features

  1. Parsing Incoming Requests
  2. Using Express Router
  3. Adding a 404 Error Page
  4. Filtering Paths
  5. Serving HTML Pages
  6. Serving Files Statically

What is Express.js

Express.js is a minimal and flexible web application framwork that provides a robust set of features for building web applications and APIs. It designed to make the process of building web server and applications with Node.js much simpler and more intuitive.

Key features of Express.js include:

  • Robust routing system
  • HTTP utility methods for generating responses
  • Middleware support for extending functionality
  • High performance
  • Support for various template engines
  • Error handling

Express.js simpliefies what would otherwise be complex routing and middleware implemention in vanilla node.js

Example:

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

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

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Installing Express.js

To use Express.js in your project, you need to install it via npm (Node Package Manager)

Steps:

1. Initialize a new Node.js project (if not already done):

mkdir my-express-app
cd my-express-app
npm init -y

2. Install Express.js:

npm install express

3. Create your main application file (e.g., app.js or index.js):

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

app.get('/', (req, res) => {
  res.send('Express successfully installed!');
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

4. Run your application:

node app.js

Adding Middleware & How Middleware Works

Middleware functions are functions that have access to the request object (req), the response object(res), and the next middleware function in the application’s request-response cycle.

middleware functions can:

  • Execute any code
  • Make changes to request and response objects
  • End the request-response cycle
  • Call the next middleware in the stack

How Middleware works:

  1. next(): This function passes control- to the next middleware function. If you don’t call next(), the requestt will be left handing.
  2. res object: Used to send response to the client. Once a response is sent the request-response cycle ends unless next() is called.

Example of Middleware

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

// Logger middleware
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
  next(); // Pass control to the next middleware
});

// Middleware for specific path
app.use('/api', (req, res, next) => {
  console.log('API route accessed');
  next();
});

// Route handler middleware
app.get('/', (req, res) => {
  res.send('Hello from Express!');
});

// Error handling middleware (must have 4 parameters)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

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

Handling Different Routes

Express.js provides a simple and powerfull routing system that allows you handle different HTTP methods and URL patterns.

Basic Routing:

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

// GET method route
app.get('/', (req, res) => {
  res.send('GET request to homepage');
});

// POST method route
app.post('/', (req, res) => {
  res.send('POST request to homepage');
});

// Route with URL parameters
app.get('/users/:userId', (req, res) => {
  res.send(`User ID: ${req.params.userId}`);
});

// Route with query parameters
app.get('/search', (req, res) => {
  const query = req.query.q;
  res.send(`Search query: ${query}`);
});

// Route with regular expression
app.get(/.*fly$/, (req, res) => {
  res.send('URL path ends with "fly"');
});

app.listen(3000);

Parsing Incoming Requests

Express.js provides middleware to parse incoming request bodies in various formats. The most common oncs are JSON and URL-encoded data.

Built-in Middleware for Parsing:

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

// Parse JSON bodies
app.use(express.json());

// Parse URL-encoded bodies (form data)
app.use(express.urlencoded({ extended: true }));

app.post('/api/data', (req, res) => {
  // Access parsed data from the request body
  console.log(req.body);
  res.json({ received: req.body });
});

app.listen(3000);

For parsing other formats, additional middleware packages might be required:

  • multer for multipart/form-data (file uploads)
  • body-parser for raw and text bodies

Key Differences

Featureexpress.json()express.urlencoded()
Expected Data FormatJSON (application/json)URL-encoded (application/x-www-form-urlencoded)
Parsing BehaviorConverts JSON string to JavaScript objectConverts URL-encoded string to key-value pairs
Common Use CaseAPIs sending/receiving JSON payloadsHTML forms submitting data

Using Express Router

The Express Router is a class that helps you create modular, mountable route handlers. This is particularly useful for organizing routes in larger applications.

Example:

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

// Create a router instance
const userRouter = express.Router();
const productRouter = express.Router();

// User routes
userRouter.get('/', (req, res) => {
  res.send('User list');
});

userRouter.get('/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

// Product routes
productRouter.get('/', (req, res) => {
  res.send('Product list');
});

productRouter.get('/:id', (req, res) => {
  res.send(`Product ID: ${req.params.id}`);
});

// Mount routers on specific paths
app.use('/users', userRouter);
app.use('/products', productRouter);

app.listen(3000);

Adding a 404 Error Page

In Express.js, you can create a middleware function to handle 404 errors. This middleware should be placed after all other routes and middleware.

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

app.get('/about', (req, res) => {
  res.send('About page');
});

// Define your routes first
app.get('/', (req, res) => {
  res.send('Home page');
});

// 404 middleware - should be placed after all routes
app.use((req, res, next) => {
  res.status(404).send('404 - Page Not Found');
  // Alternatively, you can render an HTML page:
  // res.status(404).sendFile(path.join(__dirname, 'public', '404.html'));
});

app.listen(3000);

Filtering Paths

You can filter paths in Express.js by using middleware selectively on specific routes or by using route parameters and query parameters.

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

// Middleware applied only to /admin/* routes
app.use('/admin', (req, res, next) => {
  // Check if user is authenticated
  const isAdmin = req.query.admin === 'true';
  if (!isAdmin) {
    return res.status(403).send('Access denied');
  }
  next();
});

app.get('/admin/dashboard', (req, res) => {
  res.send('Admin Dashboard');
});

app.get('/public', (req, res) => {
  res.send('Public Area - No Authentication Required');
});

app.listen(3000);

Using Route Parameters for Filtering:

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

// Get products by category
app.get('/products/:category', (req, res) => {
  const category = req.params.category;
  // In a real app, you would filter products by category
  res.send(`Products in category: ${category}`);
});

// Filter by query parameters
app.get('/search', (req, res) => {
  const query = req.query.q || '';
  const minPrice = req.query.minPrice || 0;
  const maxPrice = req.query.maxPrice || Number.MAX_VALUE;
  
  res.send(`Search results for: ${query} (Price range: ${minPrice}-${maxPrice})`);
});

app.listen(3000);

Serving HTML Pages

Express.js allow you to serve HTML pages using various methods like res.sendFile() or template engines.

Using res.sendFile():

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

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.get('/about', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'about.html'));
});

app.listen(3000);

Using a Template Engine (EJS):

First, install EJS:

npm install ejs

Then set it up:

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

// Set up EJS as the template engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

app.get('/', (req, res) => {
  // Render the index.ejs template with data
  res.render('index', { title: 'Home Page', message: 'Welcome to Express!' });
});

app.listen(3000);

Example EJS template (views/index.ejs):

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
</head>
<body>
  <h1><%= message %></h1>
</body>
</html>

Serving Files Statically (express.static())

Express.js provides the express.static middleware for serving static files like images, CSS file, and JavaScript files.

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

// Serve static files from the 'public' directory
app.use(express.static(path.join(__dirname, 'public')));

// You can also specify a mount path
app.use('/assets', express.static(path.join(__dirname, 'public')));

// Serve from multiple directories
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'uploads')));

app.get('/', (req, res) => {
  res.send('Check out our <a href="/images/logo.png">logo</a>');
});

app.listen(3000);

With this setup:

  • A file like public/images/logo.png would be accessible at http://localhost:3000/images/logo.png
  • With the mount path, the same file would also be accessible at http://localhost:3000/assets/images/logo.png

Directory structure example:

project/
├── app.js
├── public/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── images/
│       └── logo.png
└── views/
    └── index.ejs

Check this code for Example: https://github.com/itscsp/learn-Node.js/tree/main/100-Project-blog-app