Serving a dynamic website with Node.JS and ExpressJS using doT for templating

In this post I am going to describe how to set up and get started on making a dynamic website with Node.JS from scratch. But first…

Let’s Backtrack…

You may want to skip this section if you’re already familiar with Node.JS and ExpressJS; but I want to take a second to backtrack and explain how exactly this whole thing fits together. Node.JS is a framework and runtime for executing javascript using Google Chrome’s V8 javascript engine. When you run a website from Node.JS you are not using a webserver like IIS or Apache, but your node application itself is the web server. Without anything else, one has to use node’s ‘http’ module to create a web server. While this is perfectly functional, it requires doing a lot of overhead to do anything useful (e.g. to send content you have to add the appropriate content-length header yourself, it doesn’t do caching, etc.). This is where ExpressJS comes in. Express is a module for Node that takes care of the web server part – it exposes functionality to quickly and easily create your web server and start serving content. It handles cookies, sessions, request routing, url parsing, and pretty much everything you could ever need for running a website through Node. Together they are an incredibly powerful combination. The only thing missing from this combination is a templating engine. Express allows you to ‘register’ a wide variety of templating engines such as Jade (which is seemingly the most popular one) and doT (which is similar, but more light-weight). These templating engines allow you to serve up HTML pages that have dynamic content.

Setting up ExpressJS

So in your javascript file you will want to require(‘express’) as usual. You will also need to ‘npm install dot’ and ‘npm install express-dot’. This second module provides a simplified layer between express and doT which will take some of the hassle away from you of trying to get them to work together.

Static files

In your solution you will definitely want to have some static files that are not templated, such as client side javascript, css files, and images. For this, you will create a folder to put your static items into (say we call it /public) and then tell Express to serve those files as static.

We do this as follows:

app.use('/css',express.static(__dirname+'/public/css'));
app.use('/img',express.static(__dirname+'/public/img'));
app.use('/js',express.static(__dirname+'/public/js'));

You could of course just do something as follows, if this is more appropriate to your solution:

app.use(express.static(__dirname+'/public'));

In my solution this wasn’t what I wanted so I chose to be more selective about what I’m serving as public.

Configure ExpressJS to use doT

Now that we have our static files working, we will need a view folder. Create ‘/view’ and then create two html files in it. One will be called ‘layout.html’ and one will be called ‘index.html’. Let me explain how doT works for a minute: When you tell doT to render a page using a view, it will find the view you request and render it, but then it will also look for a view with the same extension but called ‘layout’ and then in layout it will replace {{=it.body}} with whatever content was rendered by the view you requested. This way you can have a ‘main’ template that is the same for all pages, and then a varying template for different pages that go together so that you can reuse it. The behavior of injecting your requested view into the layout view is overridable because in certain situations you will not want that, but this is how the base functionality works.

Configure your app as such (note that I left in the bits about static files as above):

app.configure(function(){
	app.set('views', __dirname+'/views');
	app.set('view engine', 'dot');
	app.engine('html', doT.__express);
	app.use('/css',express.static(__dirname+'/public/css'));
	app.use('/img',express.static(__dirname+'/public/img'));
	app.use('/js',express.static(__dirname+'/public/js'));
});

So what this does is that when the express application is starting up and undergoing its configuration, we tell it that the views are located in the /views folder, then we tell it to use the ‘dot’ templating engine, and finally we tell it that the extension for our views is ‘html’.

Rendering Views

So now that we have all that up and running, it’s time to actually handle requests. Create the following ‘get’ handler for your express app:

app.get('/', function(req, res){
	var templateData = {...};
	res.render('index.html', templateData);
});

For the templateData variable, anything you put in there will be passed to your template. So for instance, if my templateData object contained a property called ‘title’ I could reference it in my index.html as such to display it:

<h1>{{=it.title}}</h1>

There are many other functionalities of doT. I won’t go into details of each one, but here’s some examples:

Conditionals

If a user is an admin display one thing, if they’re just a logged in user display something else, and if they’re not logged in then display something completely different:

{{? loggedIn && isAdmin }}
Case One
{{?? loggedIn }}
Case Two
{{?? true }}
Case Three
{{?}}

Definitions

So what this is very useful for in my case is that my main template (layout.html) contains pieces that need to go inside of my body layout. Specifically, my footer actually needs to be inside the <div> of the container in the body, and I have some javascript include tags that need to be on every page, but after which I may need more javascript relevant only to the page its on. In my layouts.html I define the pieces as follows:

{{#def.footer:
My Footer Goes Here!
:}}

… and then in my body template I make use of it by doing this:

{{##def.footer}}

Closing Thoughts

Ever since I found out about ExpressJS and the templating engines that go with it, I’ve had almost zero inclination to use PHP again. Node.JS performs more efficiently (excluding some specific use cases) and is easier to develop for. Of course there are different problems to be tackled in the Node world, but ExpressJS+Node is truly a power house for backend web development. I strongly recommend trying it out.

Update

By request, I have created a new blog article about a basic scaffolding for a node.js powered website that basically acts as a downloadable example for the above, and also incorporates bootstrap on the frontend. Check it out!


7 Comments on “Serving a dynamic website with Node.JS and ExpressJS using doT for templating”

  1. Jim Butler says:

    this is a great article! i’d like to suggest though, that you link up some of the packages you’re mentioning. i find it rather annoying to force user to do searches on their own, after all links are building the internet. also, a downloadable demo would be nice.

  2. BanditVibe says:

    Where is the dot-express module?
    npm install dot-express
    dot-express' is not in the npm registry

  3. Hi, that was a outstanding piece of writing!

    Lots of incredible suggestions, I am happy that I
    discovered it.

    I am definitly going to take a note of your blog!
    :-)

  4. Venisoft says:

    Hi,
    What about app object. This variable belongs to which module http/dot/express-dot/express.

    I am getting app.set(‘www’, __dirname+’/www’);

    Plz help.

    • Petro says:

      Hi Veni, this article is based around express version 3, which is not the latest version anymore. Currently express is at version 4 which underwent many major changes so perhaps what you’re trying to do is not working because the way you’re supposed to do it has changed. That being said, have a look at this API reference page for app.set http://expressjs.com/4x/api.html#app.set and see if you can find your answer there. It looks like this ‘www’ field you’re trying to set is not in the manual so maybe you’re looking for something else. I think you may need to do this instead based off what I see: app.use(express.static(__dirname + ‘/www’));


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>