Express.js Overview: From Node’s HTTP to a Full Framework
Learn why Express.js is preferred over the Node.js HTTP module and how it simplifies back-end development.
Handling HTTP requests is at the heart of every web application, whether you’re serving pages, processing form submissions, or fetching data. While Node.js provides a built-in http
module, setting up a server from scratch requires a lot of boilerplate code to efficiently manage different requests.
This is where Express.js comes in. As a minimal yet powerful web framework for Node.js, Express simplifies request handling, reducing the code needed to build robust back-end applications.
A defining trait of Express is that it’s unopinionated, meaning it doesn’t enforce a specific project structure or require certain tools. Developers have full control over organizing their code and structuring their applications. This flexibility makes Express a great choice for everything from small prototypes to large-scale applications that require customization.
Before diving into Express, let’s explore why handling HTTP requests manually can be challenging.
The pain points of using the http
module
The built-in http
module in Node.js allows us to create a web server, but handling multiple request types requires explicitly checking the request’s URL and method before responding. We must also parse incoming data, handle errors, and structure reusable logic ourselves.
const http = require("http"); const server = http.createServer((req, res) => { if (req.url === "/" && req.method === "GET") { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Welcome to our homepage!"); } else if (req.url === "/about" && req.method === "GET") { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("About us page"); } else { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Page not found"); } }); server.listen(3000, () => { console.log("Server running on port 3000"); });
Why is this approach challenging?
Too much manual work: We have to manually check
req.url
andreq.method
for every request.Code gets harder to manage: Adding more requests requires additional
if
conditions.Manually setting headers: We must explicitly define response headers each time.
Clearly, we need a better solution. This is where Express.js helps us by automating these tasks.
How Express.js makes development easier
While Express.js builds on Node’s built-in http
module, it provides a cleaner interface for handling HTTP requests and eliminates repetitive code. The example below behaves the same as the previous example, but is much more concise.
const express = require("express"); const app = express(); app.get("/", (req, res) => { res.send("Welcome to our homepage!"); }); app.get("/about", (req, res) => { res.send("About us page"); }); app.use((req, res) => { res.status(404).send("Page not found"); }); app.listen(3000, () => { console.log("Server running on port 3000"); });
What’s different?
Less code: No need to manually check
req.url
orreq.method
.Cleaner structure: Requests are handled using simple
app.get()
calls.Automatic response handling:
res.send()
sets headers for us.Error handling is built-in: The
app.use()
method catches all undefined routes.
By using Express, we write less boilerplate code and improve code organization.
Setting up an Express server
Now that we understand why Express is useful, let’s set up a basic Express server.
const express = require("express"); const app = express(); app.get("/", (req, res) => { res.send("Hello, Express!"); }); app.listen(3000, () => { console.log("Server running on port 3000"); });
Explanation:
Line 1: This imports the Express module using
require("express")
.Line 2: This calls
express()
to create an Express application instance, and stores it inapp
.Line 4: This defines a request handler that responds to
GET
requests at/
.Line 5: This sends a response without needing to manually set headers.
Lines 8–10: This starts the server on port 3000.
With just a few lines of code, we now have a fully functional web server!
Key takeaways:
Express simplifies server-side development compared to the built-in HTTP module.
The request-response cycle is handled automatically by Express.
Express provides built-in request handling and response management.
With Express, we can build web servers quickly and efficiently.
Exercise: Creating an Express server
Task:
Create an Express server in server.js
that listens on port 4000. Add a GET /welcome
route that responds with "Welcome to Express!"
.
// Implement your solution here...