Getting Started with Express.js
- What is Express.js?
- Installing Express.js
- Adding Middleware & How It Works
- Understanding
next() - The response object (
res)
- Understanding
- Handling Different Routes
- Assignment: Building a Simple Book API
Advanced Express.js Features
- Parsing Incoming Requests
- Using Express Router
- Adding a 404 Error Page
- Filtering Paths
- Serving HTML Pages
- 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:
- next(): This function passes control- to the next middleware function. If you don’t call
next(), the requestt will be left handing. - 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:
multerfor multipart/form-data (file uploads)body-parserfor raw and text bodies
Key Differences
| Feature | express.json() | express.urlencoded() |
|---|---|---|
| Expected Data Format | JSON (application/json) | URL-encoded (application/x-www-form-urlencoded) |
| Parsing Behavior | Converts JSON string to JavaScript object | Converts URL-encoded string to key-value pairs |
| Common Use Case | APIs sending/receiving JSON payloads | HTML 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.pngwould be accessible athttp://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