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.