Express.js Explained – Simplify HTTP Request Handling in Node
Express.js is a web framework that simplifies server-side HTTP request handling in Node.js. It extends Node’s HTTP module with built-in features such as routing and middleware, helping developers to build web applications and APIs efficiently without repetitive code.
This guide explains the purpose of Express.js by guiding you through a basic application setup. To begin, let’s ensure your system is ready for the steps ahead.
Set Up Your System
Section titled “Set Up Your System”Make sure your system has Node.js 18 (or greater).
Create a Project Directory
Section titled “Create a Project Directory”Use the mkdir command to create a new project directory:
mkdir codesweetly-expressjs-app-001Next, navigate to your project directory using the command line.
cd path/to/codesweetly-expressjs-app-001Create a package.json File
Section titled “Create a package.json File”Once you’re in the project folder, use NPM to create a package.json file.
npm init -yNext, open the package.json file and delete the main field.
Configure the Project as an ES Module Application
Section titled “Configure the Project as an ES Module Application”This guide uses ES Modules in all JavaScript files, so update the type field in your project’s package.json file to module.
{ "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "type": "module"}Why Express.js?
Section titled “Why Express.js?”Express.js provides methods such as app.get(), res.send(), and res.json() to simplify handling web requests. The following steps demonstrate how to install and use Express in a basic Node.js application.
1. Install Express
Section titled “1. Install Express”npm install express2. Create the entry script
Section titled “2. Create the entry script”Create a file to start the server and listen for browser connections.
touch index.js3. Use Express.js to configure the project’s Node.js web server
Section titled “3. Use Express.js to configure the project’s Node.js web server”Open the new JavaScript file and use Express.js to set up a web server:
// Add the Express module:import express from "express";
// Create a new Express application instance:const app = express();
// Set the port number where the server will run and listen for requests:const port = 3000;
// Create a route handler for GET requests to the "/" path:app.get("/", (req, res) => res.send("Hello, world!"));
// Run the server on the specified port:app.listen(port, () => { console.log(`Server running at http://localhost:${port}`);});Here’s what the code above does:
- Create an Express application instance to access Express APIs, such as routers and middleware, which simplifies HTTP request handling in Node.js.
- Use Express’s
app.get()method to define how the server handles HTTP GET requests to the/route. - Use Express’s
res.send()method to send an HTTP response and automatically set the appropriate headers based on the data type provided. - Use Express’s
app.listen()method to start the Node.js HTTP server on a specific port and execute a callback when the server begins listening for client requests.
4. Run the Express.js web server
Section titled “4. Run the Express.js web server”The node filename.extension command is a universal CLI tool for running all Node.js scripts, including those using Express.js to handle HTTP requests.
node index.jsRaw Node.js Code vs. Express.js Code
Section titled “Raw Node.js Code vs. Express.js Code”While you can use Node’s native HTTP API to handle web requests, it requires manual configuration, such as inspecting each request’s method and URL, setting response headers, and converting objects to JSON.
Express abstracts repetitive request-handling logic into declarative methods, simplifying Node.js web server development.
Below are two examples comparing Node.js web server code written with the native HTTP module and with Express methods.
Example 1: Using raw Node.js to handle web requests
Section titled “Example 1: Using raw Node.js to handle web requests”The following web server uses only Node’s built-in HTTP module to handle routes for the home page (/), books page (/books), and unavailable pages (404 error).
import { createServer } from "node:http";const port = 3000;
const server = createServer((req, res) => { if (req.method === "GET" && req.url === "/") { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Welcome to the homepage!"); } else if (req.method === "GET" && req.url === "/books") { const books = [ { id: 1, name: "Code React Sweetly" }, { id: 2, name: "Creating NPM Package" }, ]; res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify(books)); } else { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Page not found"); }});
server.listen(port, "localhost", () => { console.log(`Raw Node server running at http://localhost:${port}`);});The snippet above uses Node’s native http module to build a web server that accepts and responds to browser connections. With raw Node.js, you must manually handle the following for each route:
- Routing to the correct endpoint:
if (req.method === "..." && req.url === "...") - Response header configuration:
res.writeHead(...) - JSON formatting:
JSON.stringify(...)
Now, let’s see how to build the same web server using Express.
Example 2: Using Express.js to handle web requests
Section titled “Example 2: Using Express.js to handle web requests”The following web server uses Express methods to handle routes for the home page (/), books page (/books), and unavailable pages (404 error).
import express from "express";const app = express();const port = 3000;
app.get("/", (req, res) => { res.send("Welcome to the homepage!");});
app.get("/books", (req, res) => { const books = [ { id: 1, name: "Code React Sweetly" }, { id: 2, name: "Creating NPM Package" }, ]; res.json(books);});
app.use((req, res) => { res.status(404).send("Page not found");});
app.listen(port, "localhost", () => { console.log(`Express server running at http://localhost:${port}`);});The snippet above uses Express.js to build a web server that accepts and responds to browser connections. Express simplifies the following tasks:
- Routing logic: Express.js provides simple route declarations like
app.get(),app.post(), andapp.delete(), eliminating the need for complex conditional logic to checkreq.urlandreq.methodfor each route. - Response header configuration: Express automatically sets response headers and status codes with the argument to
res.send(), eliminating the need to manually configureres.writeHead(...)for each endpoint. - JSON formatting: Express’s
res.json()method automatically converts JavaScript objects into valid JSON responses, handling serialization and headers for you.
Important Stuff to Know About Creating Express.js Web Servers in Node.js
Section titled “Important Stuff to Know About Creating Express.js Web Servers in Node.js”Keep the following key points in mind when creating Express.js servers in your Node.js project.
Most Express.js developers call app.listen() last
Section titled “Most Express.js developers call app.listen() last”It’s common to call app.listen() last in an Express.js app. This way, all your routes, middleware, and error handlers are set up before the server starts listening for requests.
You can set the port number using environment variables
Section titled “You can set the port number using environment variables”The port variable is usually written as follows when defined in an environment variable:
const port = process.env.PORT || 3000;The above snippet instructs Node to use the port environment variable value, or default to 3000 if it’s not set. So, executing the following command in the terminal will set the port to 8000.
PORT=8000 node index.jsCommon Express.js response methods
Section titled “Common Express.js response methods”Here are some common response methods you’ll use in Express.js:
res.send(): Send an HTTP response to the client and automatically set the appropriate response headers based on the data type provided as the method’s argument.res.json(): Send JSON responses to the client and automatically set the response’sContent-Typeheader toapplication/json.res.redirect(): Redirect the client’s request to a different URL.res.render(): Render a template engine’s view and send the resulting HTML string to the client.res.status(): Set the response’s HTTP status code without ending the request-response cycle. You can chain other response methods to it, for example,res.status(404).send("404 Error: Page not found"). This method is not needed if the status code is200(the default).res.end(): End the request-response cycle without sending any data to the client.
Express’s response methods do not terminate the HTTP request handler’s execution
Section titled “Express’s response methods do not terminate the HTTP request handler’s execution”While response methods like res.send() close the HTTP request-response cycle, they do not end the execution of the route handler function.
Here’s an example:
app.get("/", (req, res) => { // This sends a text response to the client and ends the request-response cycle, but does not end the route handler's execution: res.send("Hello, client!");
// This logs the string to the console because the function is still running: console.log("Hello, devs!");
// This will cause an error because the request-response cycle is closed, so you cannot send additional responses to the client during the callback's execution: res.send("Hello, client again!");});The console.log() statement in the example above works because the request handler is still running. The res.send("Hello, client!") line only ends further HTTP responses; it does not stop the callback’s execution.