A Comprehensive Guide to Express.js
A Comprehensive Guide to Express.js
Express.js is a minimal and flexible web application framework for Node.js that simplifies the development of server-side applications. It provides a rich set of features for building web and mobile applications, making it easier to handle HTTP requests, manage middleware, and serve static files. This guide covers the essential aspects of Express.js, including its methods, middleware, routing, MVC architecture, file handling, and templating.
Core Features of Express.js
HTTP Methods
Express supports various HTTP methods to handle different types of requests:
- GET: Retrieve data from the server.
app.get("/path", (req, res) => { res.send("GET request to the homepage"); });
- POST: Send data to the server.
app.post("/path", (req, res) => { res.send("POST request to the homepage"); });
- PUT: Update existing data on the server.
app.put("/path", (req, res) => { res.send("PUT request to the homepage"); });
- DELETE: Delete data from the server.
app.delete("/path", (req, res) => { res.send("DELETE request to the homepage"); });
- PATCH: Apply partial modifications to a resource.
app.patch("/path", (req, res) => { res.send("PATCH request to the homepage"); });
- OPTIONS: Describe the communication options for the target resource.
app.options("/path", (req, res) => { res.send("OPTIONS request to the homepage"); });
- HEAD: Similar to GET, but transfers only the status line and header section.
app.head("/path", (req, res) => { res.send("HEAD request to the homepage"); });
- ALL: Handle all HTTP methods for a specific path.
app.all("/path", (req, res) => { res.send("Handling all HTTP methods"); });
Middleware in Express
Middleware functions are essential for processing requests. They have access to the request and response objects and the next middleware function. Middleware types include:
- Application-Level Middleware: Bound to an instance of the app object.
app.use((req, res, next) => { console.log("Time:", Date.now()); next(); });
- Router-Level Middleware: Similar to application-level but bound to an instance of express.Router().
const router = express.Router(); router.use((req, res, next) => { console.log("Request URL:", req.originalUrl); next(); });
- Error-Handling Middleware: Handles errors with four arguments: err, req, res, next.
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send("Something broke!"); });
- Built-In Middleware: Provided by Express, like express.json() and express.static().
app.use(express.json()); app.use(express.static("public"));
- Third-Party Middleware: Developed by the community, such as body-parser and morgan.
const bodyParser = require("body-parser"); const morgan = require("morgan"); app.use(bodyParser.json()); app.use(morgan("dev"));
Handling POST Requests
POST requests are used to send data to the server. Express handles POST requests using app.post() and requires middleware for parsing request bodies.
- JSON Body Parsing:
app.use(express.json());
- URL-encoded Body Parsing:
app.use(express.urlencoded({ extended: true }));
- Handling File Uploads: Use third-party middleware like multer.
const multer = require("multer"); const upload = multer({ dest: "uploads/" }); app.post("/upload", upload.single("file"), (req, res) => { res.send(`File uploaded: ${req.file.originalname}`); });
MVC Architecture in Express
The Model-View-Controller (MVC) design pattern separates application logic into three interconnected components:
- Model: Manages data and business logic.
const mongoose = require("mongoose"); const userSchema = new mongoose.Schema({ name: String, email: String, password: String, }); const User = mongoose.model("User", userSchema); module.exports = User;
- View: Renders data to the user, typically using templating engines.
<!-- views/index.hbs --> <!DOCTYPE html> <html> <head> <title>{{title}}</title> </head> <body> <h1>{{message}}</h1> </body> </html>
- Controller: Handles user input, interacts with the Model, and renders the View.
const express = require("express"); const router = express.Router(); const User = require("../models/user"); router.get("/", async (req, res) => { const users = await User.find(); res.render("index", { title: "User List", message: "Welcome to the User List", users, }); }); module.exports = router;
Sending Files in Express
Use res.sendFile() to send files to the client. Ensure to handle potential errors.
- Using path.join():
const path = require("path"); const filePath = path.join(__dirname, "public", "example.txt"); app.get("/file", (req, res) => { res.sendFile(filePath); });
- Handling Errors:
app.get("/file", (req, res) => { res.sendFile(filePath, (err) => { if (err) { res.status(404).send("File not found"); } }); });
Templating Engines
Express supports templating engines to dynamically generate HTML. Handlebars (HBS) is one such engine, known for its simplicity and readability.
- Setting Up Handlebars:
const express = require("express"); const exphbs = require("express-handlebars"); const app = express(); app.engine("hbs", exphbs({ extname: ".hbs" })); app.set("view engine", "hbs"); app.set("views", "./views"); app.get("/", (req, res) => { res.render("index", { title: "Home", message: "Hello, World!" }); });
- Layouts and Partials: Manage common elements across your application.
- Layouts:
<!-- views/layouts/main.hbs --> <!DOCTYPE html> <html> <head> <title>{{title}}</title> </head> <body> {{{body}}} </body> </html>
- Partials:
<!-- views/partials/header.hbs --> <header><h1>My Website</h1></header>
Conclusion
Express.js offers a robust framework for building server-side applications with Node.js. Its support for various HTTP methods, middleware, and templating engines like Handlebars makes it a powerful tool for creating scalable and maintainable web applications. By leveraging Express’s features and following best practices such as MVC architecture and proper file handling, developers can build efficient and dynamic web applications.