Full series: Building website with Nodejs - A post from my experience
Previous post: Nodejs - Express with ejs/stylus basics

Middleware

Simply, middleware are just functions for handling requests from client. Each request can have be associated with a stack of middleware. That means when you have several of handler functions associated with one request, they will be executed sequentially. Back to the example from my previous post

app.get('/', middleware1);

function middleware1(req, res){
  res.render('index', { title: 'Express', check: true });
};

In this example, there is only one middleware (handler) function for the GET request to /. Now we will add one more middleware, or maybe more if you want

app.get('/', middleware1, middleware2);

function middleware1(req, res, next){
  // do something here
  // ...

  // activate the next middleware, otherwise, the next middleware will never be
  // called and the client will wait until timeout
  next();
};

function middleware2(req, res){
  res.render('index', { title: 'Express', check: true });
};

You can also signal an error by passing it to the first argument of next() function

function middleware1(req, res){
  // do something here
  // ...
  
  next('error message');
};

Middleware can be used for several purposes such as authentication and authorization. You can follow the link to the full series at the beginning of this post and find the post that I wrote about authentication in Express. Middleware can also be used in setting common variables for displaying in layout (refer to the next section).

Layout in Express EJS

For Express 3.x, if you want to use layout, you need to install ejs-locals.

$ npm install --save ejs-locals

In the app.js file, add these 2 lines before app.set('view engine', 'ejs');

// add these 2 lines
var engine = require('ejs-locals');
app.engine('ejs', engine);

// before this line
app.set('view engine', 'ejs');

Open the views folder, create a file named layout.ejs

<!DOCTYPE html>
<html>
  <head>
    <title>My title</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <%- body %>
  </body>
</html>

There is nothing special here except the <%- body %> tag. It’s the place holder and will be replaced by the content of the page that uses this layout. Next, create another page to consume this layout, for example, index.ejs

<% layout('layout') -%>

<p>The content of the page appears here</p>

There is one problem with the layout. That is when you want to render a variable in the layout using <%= varName %>. Continue with the above example, if there is a variable named varName inside layout.ejs and you want it to display based on the page that you are viewing, you can not pass the variable through the the render function normally like this

res.render('index', { title: 'Express', varName: 'value' });

You will get the error that varName is not defined because the variable is only available inside the index.ejs view, not the layout. To display it in the layout, you need to assign it to res.locals

function handler(req, res, next){
  res.locals.varName = 'value';
  res.render('index', { title: 'Express'});
};

And then in layout.ejs just echo the variable normally

<%= varName %>

For convenience, you can create a middleware to set common values (current logged in user for instance) and pass it to the routing function.