In order to explore middleware, we'll create some basic middleware. Just following where we call app.use registering our Express static middleware, we'll call app.use again:
app.use(express.static(__dirname + '/public'));
app.use();
Now app.use is how you register middleware, and it takes a function. So, we'll pass in an arrow function (=>):
app.use(() => {
});
The use function takes just one function. There is no need to add any other arguments. This function will get called with the request (req) object, the response (res) object and a third argument, next:
app.use((req, res, next) => {
});
Now request and response objects, these should seem familiar by now. They're the exact same arguments we get whenever we register a handler. The next argument is where things get a little trickier. The next argument exists so you can tell Express when your middleware function is done, and this is useful because you can have as much middleware as you like registered to a single Express app. For example, I have some middleware that serves up a directory. We'll write some more that logs some request data to the screen, and we could have a third piece that helps with application performance, keeping track of response times, all of that is possible.
Now inside app.use function, we can do anything we like. We might log something to the screen. We might make a database request to make sure a user is authenticated. All of that is perfectly valid and we use the next argument to tell Express when we're done. So if we do something asynchronous, the middleware is not going to move on. Only when we call next, will the application continue to run, like this:
app.use((req, res, next) => {
next();
});
Now this means if your middleware doesn't call next, your handlers for each request, they're never going to fire. We can prove this. Let's call app.use, passing in an empty function:
app.use((req, res, next) => {
});
Let's save the file and in the Terminal, we'll run our app using nodemon with server.js:
nodemon server.js

I'll move into the browser and I'll make a request for the home page. I'll refresh the page and you can see that up top, it is trying to load but it's never going to finish:

Now it's not that it can't connect to the server. It connects to the server just fine. The real problem is that inside our app, we have middleware that doesn't call next. To fix this, all we'll do is call next like this:
app.use((req, res, next) => {
next();
});
Now when things refresh over inside the browser, we get our Home Page exactly as we expect it:

The only difference is now we have a place where we can add on some functionality.