Easy Guide To Understanding ExpressJS Middleware For Rapid App Development
Tags: node, javascript, webdev, tutorial
Published: 2023-01-20 22:26:53

An Express app is largely composed of middleware function calls that enable developers to quickly build web applications.

In this article, we will learn what middleware is, the importance of middleware, and how to write your own middleware for ExpressJS applications.

By the end of the article, you should know :

* What middleware is
    
* The Importance of middleware
    
* The built-in Express middleware functions
    
* How to create and use middleware function in our Express app.
    

Prerequisites:

Before getting started, you should have knowledge on:

* What ExpressJS is
    
* [How to create an Express App](https://dev.to/efkumah/easy-steps-to-create-an-expressjs-application-3gb8)
    

## Introduction to Middleware

Whenever an Express app receives a request, it needs to send back a response. A middleware component sits between a request and a response.

It is those methods/functions/operations that are called between processing the request and sending the response in an Express app.

Middleware executes whenever the server receives a request and has access to the request object (`req`), the response object(`res`), and a `next()` function.

## How middleware works

Consider an analogy, where you are a property owner with tons of apartments to let out to tenants. However, you are selective about the type of tenant that occupies the apartment. You want tenants with specific social classes and ethnicities.

To schedule a viewing, potential clients must call you.

To avoid the headache of screening all potential tenants, you hire a real estate agent to oversee these activities. Whenever a potential tenant requests an apartment, the agent will schedule an initial meeting with the client. The agent screens a client to determine if he meets your criteria.

The agent informs you to allow the client to view the apartment once he meets all the requirements. You then pay the agent a commission for his service.

In this analogy:

* The **tenant** represents the **HTTP request** performed by the client
    
* The **real estate agent** represents the **middleware**
    
* The **property owner** represents the **server**
    

The agent (**middleware**) ensures any request by a client to access an apartment meets the criteria determined by the property owner ( **server**).

**In effect, the middleware (i.e the real estate agent) sits between the client (i.e tenant) and the server(i.e property owner ) and determines the next action to take.**

Should the client not meet the criteria, the middleware has the right to terminate the request. In effect, ending the request-response cycle.

## Importance of middleware

Middleware functions can perform the following tasks:

* Add logging and authentication functionality to our application
    
* Can be used to manipulate requests
    
* Make changes to the request and response objects
    
* Call the next middleware function in the stack
    
* Can process request objects multiple times before the server works on the request.
    
* It improves client-side rendering performance.
    

## Types of middleware functions

An Express app can use the following types of middleware:

* Application-level middleware: a type of middleware that generally runs throughout the whole application
    
* Router-level middleware: router-level middleware work just like application-level middleware except they are bound to an instance of express. Router()
    
* Error-handling middleware: the purpose of error-handling middleware is to detect and capture multiple error conditions and take corrective actions to recover from or gracefully fail in the face of those errors.
    
* Built-in middleware: middleware built into the Express application.
    
* Third-party middleware: third-party packages available that provide the functionality that our app requires.
    

We will discuss these types as we progress.

## Setting up the ExpressJS development environment

To demonstrate how middleware works, we will set up a basic ExpressJS application.

Follow these steps to set up an Express app

* Open your favorite code editor and create a project directory.
    
* Install the `package.json` file
    
* Install the `express` library in the directory
    

The following commands illustrate the above:

```javascript
mkdir middleware-tuts
cd middleware-tuts
npm init -y
npm install express
```

Create an `index.js` file and add the code snippets below to create a basic express application.

```javascript
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.send(`<h1>Home</h1>`);
});

app.listen(5000, () => {
  console.log("App has started and listening on port 5000");
});
```

You can also install `nodemon` using the command below. This will automatically restart the server whenever it detects changes to the file.

```javascript
npm install nodemon
```

Modify the `scripts` in the `package.json` file to the following:

```javascript
 "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
```

Start the application using the command below:

```javascript
npm run dev
```

Congratulations, you have created an Express app. Visit `http://localhost:5000` to view your app.

## Creating the middleware in an Express app

Because middleware is a function, we can use any preferred function declaration. We pass the function three parameters `req`, `res` and `next`.

The syntax is as below:

```javascript
const middleWareName = (req,res,next)=> {
//logic here
next() // call the next middleware
 }
```

As mentioned, one of the main tasks of middleware is to manipulate requests.

In the example below, we create a basic `logger` middleware that logs a message whenever the **client requests a resource**

```javascript
//create the middleware
const logger = (req, res, next) => {
  console.log(`Hello, you've hit our server`);
  next();
};
```

## Understanding the middleware parameters

Middleware accepts three parameters `req` and `res` objects and the `next` function.

### Manipulating the request object

* The `req` is passed as a parameter during the function declaration.
    
* Because middleware enables us to manipulate requests, in the body of the function, we can access all the available methods in the `req` object.
    

In the example below, whenever we receive a request, we log the `HTTP method` used and a message

```javascript
//declare the logger middleware
const logger = (req, res, next) => {
  console.log(req.method); // logs the http request

  //log the below whenever the client reqest for a resouce
  console.log(`Hello you've hit our server`);
  next();
};
```

If the client is requesting data, the output will be:

```javascript
GET
Hello you've hit our server
```

### Manipulating the response object

The middleware can also manipulate the `res` object.

In the example below, we use the `res.send()` method to send back a response to the client.

```javascript
//declare a logger middleware
const logger = (req, res, next) => {
  console.log(req.method); //logs the http reqest method
  //send a response to the client
  res.send(`<h1>Middleware responded</h1>`);
};
```

**Whenever you use the** `res` **object in the function's body, it will not allow any request to go past it.**

In effect, any other logic we may have implemented in the app will not be accessed.

### Accessing the next() function.

The `next()` is a function that enables us to invoke the next middleware in the middleware stack.

Whenever the current middleware function does not end the request-response cycle, it must call `next()` to pass control to the next middleware else the request will be left hanging (evidenced by the browser always reloading).

Below is how we pass the control to the next middleware

```javascript
const logger = (req, res, next) => {
  ... // all other logic here
  next() // call the next middleware
};
```

## Using the middleware

Until now, we have learned what middleware is and the functions of all the parameters.

Let's now see how we use declared middleware.

The syntax below illustrates how to use a middleware function

```javascript
app.use([path,] callback [, callback...])
```

* The `app.use()` connects the declared middleware function(s) to our application at the specified path.
    
* The `path` represents the route for which the middleware function is invoked.
    
* The `callback` represents a middleware function, a series of middleware functions (separated by commas), or an array of middleware functions that will be executed.
    

The code snippet below is how we will use the `logger` middleware function

```javascript
//using the logger middleware
app.use("/", logger);
```

In the example above, whenever the client visits the home route (`/`) the `logger` middleware is executed.

Middleware staged without a `path` , for instance, `app.use(middleware)` will be executed for **every request to the app**.

### Middleware order of execution

Middleware is executed in the order in which they are added.

Consider the example below:

```javascript
app.use(middleware1)
app.use(middleware2)
```

`app.use(middleware1)` will be executed before `app.use(middleware2)`

### Using multiple middlewares

In our `app.use()`, we can declare an array of middleware functions that will be executed depending on the route requested.

In the code below, we declare the `query`middleware in addition to the `logger` middleware.

```javascript
//declare the logger middleware
const logger = (req, res, next) => {
  console.log(req.method); // logs the http request

  //log the below whenever the client reqest for a resouce
  console.log(`Hello you've hit our server`);
  next();
};

//query middeleware
const query = (req, res, next) => {
  console.log(req.query)
  next();
};
```

The `query`middleware also sits between the request-response cycle and can manipulate requests.

With this example, the `req.query` object becomes populated with the query strings. These query strings are key-value pairs and start after the question mark in any URL.

For instance [http://localhost:3000/dashboard/user?name=emmanuel&age=25](http://localhost:3000/dashboard/user?name=emmanuel&age=25)

The output will be :

```javascript
{ name: 'emmanuel', age: '25' }
```

Let's now use the declared middleware. The syntax below indicates how to use a series of middleware in our application

```javascript
//array of middlewares
app.use([mddleware1, middleware2]);
```

We can use the `logger` and `query`middlewares like the below:

```javascript
//use the middlewares
app.use([logger, query]);
```

### Registering the path to execute the middleware

Depending on the `http method` use, we can specify the path that all the declared middleware will be executed

The syntax is as below:

```javascript
app.method(path, middleware, (req, res) => {
  //do something here
});
```

Assuming, we want the `query`middleware to be executed only when the clients request a resource on the `path` : `dashboard/user` , we define it as below:

```javascript
app.get("/dashboard/user", query , (req, res) => {
  //do something here
});
```

In effect, the `query`middleware will only be invoked when the path specified in our app matches that of the client whiles the `logger` middleware executes when the client requests a resource on the root `/`.

The complete code for declaring and using middleware is as below:

```javascript
const express = require("express");
const app = express();
const port = 3000;

//declare the logger middleware
const logger = (req, res, next) => {
  console.log(req.method); // logs the http request

  //log the below whenever the client reqest for a resouce
  console.log(`Hello you've hit our server`);
  next();
};

//declare the query middeleware
const query = (req, res, next) => {
  console.log(req.query);
  next();
};

//use the middlewares
app.use([logger, query]);

//logger middleware get executed here
app.get("/", (req, res) => {
  res.send(`<h1>Hello World !</h1>`);
});

//use the query middleware
app.get("/dashboard/user", query, (req, res) => {
  // access the name key of  the query string
  const { name } = req.query;

  res.send(`<h1>Welcome ${name}</h1>`);
});

app.listen(port, () => {
  console.log(`Example app is listening on port ${port}`);
});
```

## Using Built-in middleware

Express has built-in middlewares that enable us to perform tasks.

Examples of these are:

* express.static
    
* express.json
    
* express.urlencoded
    
* express.raw
    
* express.text
    

### Using the `express.static` middleware

The `express.static` built-in middleware enables us to render static files such as images, CSS, and JavaScript files on the client-side

Unlike sending a file using the `res.sendFile()` which permits serving only single files, the `express.static()` allows all files in a specified folder to be available to the public.

The syntax is as below

```javascript
express.static(root, [options])
```

The `root` represents the root directory from which to serve static assets. If we want to render web pages, the directory should contain an `index.html` or `index.js` file which serves as the home page.

Assuming we created a `public` folder containing all the required files in our project directory, we can serve these files using the code snippet below.

```javascript
express.static('public') // built-in middleware
```

We can use this built-in middleware as below:

```javascript
app.use(express.static('public'))
```

### Using `express.json` middleware

Express provides a middleware to handle incoming data in the request's body.

The `express.json()` is a built-in middleware that enables us to recognize incoming request objects as JSON.

It enables us to send data to the server.

The syntax is as below:

```javascript
express.json([options])
```

We can use this built-in middleware as

```javascript
// parse json
app.use(express.json())
```

### Using the `express.urlencoded` middleware

The `express.urlencoded()` enable us to identify incoming request objects as strings or arrays.

This method is called using the code:

```javascript
app.use(express.urlencoded())
```

## Third-party middleware

There are many third-party middleware packages available that provide the functionality that our app requires.

Below are some examples:

* `morgan`: an `HTTP` request logger middleware
    
* `helmet`: a middleware that improves the security of your application.
    
* `compression`: a middleware that attempts to compress response bodies for all of the responses.
    

## Summary

* Middlewares are methods/functions/operations that are called between processing the request and sending the response in an Express app.
    
* It sits between the request and response cycles on an Express app
    
* It can be used to manipulate requests
    
* It can also make changes to the request and response objects
    

*<sup>This article is the day 7 post on the 30-day challenge I am undertaking to learn backend development. Please feel free, to drop some insights, comment, or share the post to your networks</sup>*