If you’ve started learning Node.js and Express.js, you’ve probably seen app.use() in almost every project:
const express = require("express");
const app = express();
app.use(express.json());
Enter fullscreen mode Exit fullscreen mode
At first glance, it may seem like just another Express function. But in reality, app.use() is one of the most important concepts in Express. It is responsible for building the request-processing pipeline by registering middleware.
In this article, we’ll explore what app.use() is, why it’s important, how it works internally, and common real-world use cases.
What is app.use()?
app.use() is a method provided by Express that registers middleware.
Middleware is simply a function that executes between receiving an HTTP request and sending the HTTP response.
Every incoming request passes through one or more middleware functions before it reaches the final route handler.
The syntax is:
app.use([path], middleware);
Enter fullscreen mode Exit fullscreen mode
-
path(optional): URL path where the middleware should run. -
middleware: Function executed for matching requests.
A middleware function looks like this:
function middleware(req, res, next) {
console.log("Middleware executed");
next();
}
Enter fullscreen mode Exit fullscreen mode
The next() function tells Express to continue processing the next middleware or route handler.
Why Do We Need Middleware?
Imagine an Express application without middleware.
app.get("/users", (req, res) => {
res.send("Users");
});
Enter fullscreen mode Exit fullscreen mode
The request directly reaches the route handler.
But real-world applications need much more:
- Validate incoming requests
- Parse JSON
- Authenticate users
- Log requests
- Handle errors
- Enable CORS
- Serve static files
Instead of repeating this logic in every route, Express lets us write reusable middleware and register it using app.use().
How Express Processes Requests
Suppose we have:
app.use((req, res, next) => {
console.log("Middleware 1");
next();
});
app.use((req, res, next) => {
console.log("Middleware 2");
next();
});
app.get("/", (req, res) => {
console.log("Route Handler");
res.send("Hello");
});
Enter fullscreen mode Exit fullscreen mode
When a request comes to /, Express executes the following pipeline:
Incoming Request
│
▼
Middleware 1
│
▼
Middleware 2
│
▼
Route Handler
│
▼
Response Sent
Enter fullscreen mode Exit fullscreen mode
Console Output:
Middleware 1
Middleware 2
Route Handler
Enter fullscreen mode Exit fullscreen mode
Express simply walks through its middleware stack in the order the middleware was registered.
The Importance of next()
Every middleware receives three parameters:
(req, res, next)
Enter fullscreen mode Exit fullscreen mode
Example:
app.use((req, res, next) => {
console.log("Request received");
next();
});
Enter fullscreen mode Exit fullscreen mode
next() tells Express:
“I’m done. Move to the next middleware.”
If you forget to call next(), Express stops processing.
Example:
app.use((req, res, next) => {
console.log("Stopped here");
});
Enter fullscreen mode Exit fullscreen mode
Now every request hangs because Express never moves to the next middleware.
Global Middleware
Without specifying a path, middleware runs for every request.
app.use((req, res, next) => {
console.log(req.method, req.url);
next();
});
Enter fullscreen mode Exit fullscreen mode
Requests:
GET /users
POST /login
DELETE /products/5
Enter fullscreen mode Exit fullscreen mode
All three execute this middleware.
This is why logging middleware is usually global.
Path-Specific Middleware
Middleware can also be attached to a specific path.
app.use("/api", (req, res, next) => {
console.log("API Middleware");
next();
});
Enter fullscreen mode Exit fullscreen mode
This middleware executes for:
GET /api/users
POST /api/login
PUT /api/orders
Enter fullscreen mode Exit fullscreen mode
But not for:
GET /
GET /about
Enter fullscreen mode Exit fullscreen mode
Express matches the URL prefix before executing the middleware.
app.use() Works for All HTTP Methods
Unlike app.get() or app.post(), app.use() doesn’t care about the HTTP method.
app.use("/users", middleware);
Enter fullscreen mode Exit fullscreen mode
Runs for:
GET /users
POST /users
PUT /users
DELETE /users
PATCH /users
Enter fullscreen mode Exit fullscreen mode
This makes it perfect for middleware like authentication.
Real-World Use Cases
1. Parsing JSON
app.use(express.json());
Enter fullscreen mode Exit fullscreen mode
Without this:
console.log(req.body);
Enter fullscreen mode Exit fullscreen mode
Output:
undefined
Enter fullscreen mode Exit fullscreen mode
With express.json():
{
"name": "John"
}
Enter fullscreen mode Exit fullscreen mode
becomes
req.body = {
name: "John"
};
Enter fullscreen mode Exit fullscreen mode
2. Logging Requests
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
Enter fullscreen mode Exit fullscreen mode
Output:
GET /users
POST /login
Enter fullscreen mode Exit fullscreen mode
3. Authentication
app.use((req, res, next) => {
if (!req.headers.authorization) {
return res.status(401).send("Unauthorized");
}
next();
});
Enter fullscreen mode Exit fullscreen mode
Every request must pass authentication before reaching the routes.
4. CORS
const cors = require("cors");
app.use(cors());
Enter fullscreen mode Exit fullscreen mode
This allows browsers to make requests from different origins.
5. Serving Static Files
app.use(express.static("public"));
Enter fullscreen mode Exit fullscreen mode
Now:
public/logo.png
Enter fullscreen mode Exit fullscreen mode
is available as:
http://localhost:3000/logo.png
Enter fullscreen mode Exit fullscreen mode
6. Mounting Routers
Suppose we have:
// users.js
router.get("/", getUsers);
router.post("/", createUser);
Enter fullscreen mode Exit fullscreen mode
Register it:
app.use("/users", userRouter);
Enter fullscreen mode Exit fullscreen mode
Routes become:
GET /users
POST /users
Enter fullscreen mode Exit fullscreen mode
This keeps applications modular and easier to maintain.
Execution Order Matters
Consider:
app.use(authMiddleware);
app.get("/dashboard", dashboard);
Enter fullscreen mode Exit fullscreen mode
Every request to /dashboard is authenticated.
Now reverse them:
app.get("/dashboard", dashboard);
app.use(authMiddleware);
Enter fullscreen mode Exit fullscreen mode
Now authentication never runs because the response is already sent.
Middleware executes strictly in the order it is registered.
Error-Handling Middleware
Express recognizes error middleware by four parameters.
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
message: err.message
});
});
Enter fullscreen mode Exit fullscreen mode
Whenever next(error) is called, Express skips normal middleware and jumps directly to this error handler.
app.use() vs app.get()
Feature
app.use()
app.get()
Purpose
Register middleware
Register a GET route
HTTP Methods
All methods
Only GET
Path Required
Optional
Required
Calls next()
Yes
Usually sends response
Used For
Logging, auth, parsing, routers
Handling GET requests
Example:
app.use("/users", middleware);
Enter fullscreen mode Exit fullscreen mode
Handles:
GET /users
POST /users
PUT /users
DELETE /users
Enter fullscreen mode Exit fullscreen mode
Whereas:
app.get("/users", handler);
Enter fullscreen mode Exit fullscreen mode
Handles only:
GET /users
Enter fullscreen mode Exit fullscreen mode
Best Practices
- Register middleware in the correct order.
- Always call
next()unless you’re sending a response. - Keep middleware focused on a single responsibility.
- Use path-specific middleware when appropriate.
- Place error-handling middleware at the end of your middleware stack.
Conclusion
app.use() is the foundation of an Express application. It lets you build a request-processing pipeline where each middleware performs a specific task before handing control to the next one.
Whether you’re parsing request bodies, authenticating users, logging requests, enabling CORS, serving static files, or organizing routes, app.use() is the mechanism that ties everything together.
Understanding how app.use() works—and especially how middleware order and next() affect request flow—is essential for writing clean, scalable, and maintainable Express applications.
If you’re learning Express, mastering app.use() is one of the biggest steps toward understanding how Express handles requests under the hood.
Thanks for reading! 🚀 If you found this article helpful, consider sharing it with fellow developers who are learning Express.js.
답글 남기기