Class 21: Express.js - Building a Web Server
In the previous class, we built a simple HTTP server using
Node.js's built-in http
module. While functional,
you might have noticed that handling different routes, parsing
request bodies, and managing middleware can quickly become
complex. This is where web frameworks come into play.
Today, we introduce Express.js, the most popular and widely used web application framework for Node.js. It provides a robust set of features for web and mobile applications, making backend development faster and more structured.
Introduction to Express.js
- What is Express.js? Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It provides a thin layer of fundamental web application features, without obscuring Node.js features that you already know.
-
Benefits of using Express.js:
- Middleware: A powerful system for handling requests and responses in a chain of functions.
- Routing: Simple and intuitive ways to define routes for different URL paths and HTTP methods.
- Robustness: Provides a solid foundation for building scalable and maintainable web applications and APIs.
- Performance: Being built on Node.js, it inherits its non-blocking I/O model, making it efficient.
- Community & Ecosystem: Large community support and a vast ecosystem of compatible middleware and libraries.
-
Comparison with pure Node.js
http
module:While the
http
module is fundamental, Express.js abstracts away much of the low-level HTTP handling. It simplifies tasks like:- Parsing URLs and query strings.
- Handling different HTTP methods (GET, POST, etc.).
- Managing request and response headers.
- Serving static files.
- Error handling.
In essence, Express.js provides a more developer-friendly and efficient way to build web servers compared to writing everything from scratch with the native
http
module.
Setting Up an Express Application
Let's create our first Express.js application.
1. Project Initialization:
First, create a new directory for your project and initialize a
Node.js project using npm init
.
mkdir my-express-app
cd my-express-app
npm init -y
This will create a package.json
file in your
project directory.
2. Installing Express:
Now, install the Express.js package as a dependency for your project.
npm install express
This command will add "express" to your
package.json
dependencies and create a
node_modules
folder.
3. Creating the Main Application File:
Create a file, typically named app.js
or
server.js
, in your project's root directory. This
file will contain your Express application's main logic.
// server.js (or app.js)
const express = require('express'); // Import the express module
const app = express(); // Create an Express application instance
const port = 3000; // Define the port number
// Define a basic route for the root URL ("/")
// When a GET request comes to "/", execute this function
app.get('/', (req, res) => {
res.send('Hello from Express!'); // Send a simple text response
});
// Start the server and listen for incoming requests on the specified port
app.listen(port, () => {
console.log(`Express app listening at http://localhost:${port}`);
});
4. Running Your Express App:
To run your Express server, open your terminal in the project directory and execute the file using Node.js:
node server.js
You should see the message
Express app listening at http://localhost:3000
.
Now, open your browser and navigate to
http://localhost:3000/. You should see "Hello from Express!".
Basic Routing
Routing refers to how an application's endpoints (URIs) respond to client requests. Express.js makes defining routes very straightforward.
HTTP Methods:
Express provides methods for all standard HTTP verbs:
app.get()
, app.post()
,
app.put()
, app.delete()
,
app.patch()
, and app.all()
(for any
HTTP method).
// server.js (continued)
// GET request to the root path
app.get('/', (req, res) => {
res.send('Welcome to the homepage!');
});
// GET request to /about
app.get('/about', (req, res) => {
res.send('This is the about page.');
});
// POST request to /data (e.g., for submitting a form)
app.post('/data', (req, res) => {
res.send('Data received via POST request!');
});
// PUT request to /items (e.g., for updating an item)
app.put('/items', (req, res) => {
res.send('Item updated via PUT request!');
});
// DELETE request to /items (e.g., for deleting an item)
app.delete('/items', (req, res) => {
res.send('Item deleted via DELETE request!');
});
// You can also chain multiple handlers for a single route
app.get('/chained', (req, res, next) => {
console.log('First handler for /chained');
next(); // Pass control to the next handler
}, (req, res) => {
res.send('Second handler for /chained. Request processed!');
});
// ... app.listen() remains the same
Route Parameters:
You can define routes with "named" parameters to capture values
from the URL. These values are available in
req.params
.
// server.js (continued)
// Route with a parameter for user ID
// Example: GET /users/123
app.get('/users/:id', (req, res) => {
const userId = req.params.id; // Access the 'id' parameter
res.send(`Fetching user with ID: ${userId}`);
});
// Route with multiple parameters
// Example: GET /products/electronics/laptop
app.get('/products/:category/:productId', (req, res) => {
const category = req.params.category;
const productId = req.params.productId;
res.send(`Fetching product '${productId}' from category '${category}'`);
});
// ... app.listen() remains the same
Request and Response Objects
In every route handler, Express provides two crucial objects:
req
(the request object) and res
(the
response object).
req
(Request Object):
The req
object represents the HTTP request and has
properties for the request query string, parameters, body, HTTP
headers, and more.
-
req.params
: An object containing properties mapped to the named route parameters. -
req.query
: An object containing a property for each query string parameter in the route.// Example: GET /search?q=nodejs&sort=asc app.get('/search', (req, res) => { const searchTerm = req.query.q; const sortOrder = req.query.sort; res.send(`Searching for "${searchTerm}", sorted: ${sortOrder}`); });
-
req.body
: Contains key-value pairs of data submitted in the request body. (Requires middleware likeexpress.json()
orexpress.urlencoded()
, which we'll cover in the next class). -
req.headers
: An object containing the request headers.
res
(Response Object):
The res
object represents the HTTP response that an
Express app sends when it gets an HTTP request.
-
res.send(body)
: Sends an HTTP response. Thebody
can be a String, Buffer, an object, or an Array. Express automatically sets the Content-Type header.app.get('/hello', (req, res) => { res.send('Hello World!'); });
-
res.json(body)
: Sends a JSON response. This method is commonly used for building APIs.app.get('/api/data', (req, res) => { const data = { message: 'Data fetched successfully', items: [ { id: 1, name: 'Item A' }, { id: 2, name: 'Item B' } ] }; res.json(data); // Sends JSON and sets Content-Type to application/json });
-
res.status(statusCode)
: Sets the HTTP status for the response. This method is chainable.app.get('/not-found', (req, res) => { res.status(404).send('Sorry, that resource was not found!'); }); app.post('/create', (req, res) => { // Assume creation was successful res.status(201).json({ message: 'Resource created successfully!' }); // 201 Created });
-
res.sendFile(path)
: Transfers the file at the given path. This is useful for serving static HTML files.const path = require('path'); app.get('/download', (req, res) => { const filePath = path.join(__dirname, 'public', 'document.pdf'); res.sendFile(filePath); });
Starting the Express Server
The app.listen()
method is used to bind and listen
for connections on the specified host and port.
// server.js
const express = require('express');
const app = express();
const port = 3000;
// ... (your routes and other app logic) ...
// Start the server
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
console.log(`Access it at: http://localhost:${port}`);
});
This method is asynchronous and returns an HTTP server object.
The callback function passed to listen
is executed
once the server has successfully started.
You now have a foundational understanding of how to set up and run an Express.js application, define basic routes, and handle requests and responses. In the next class, we'll dive deeper into Express middleware, which is a core concept for building more complex and modular applications.