Using Handlebars with Express

In this article written by Paul Wellens, author of the book Practical Web Development, we cover a brief description about the following topics:

  • Templates
  • Node.js
  • Express 4

(For more resources related to this topic, see here.)

Templates

Templates come in many shapes or forms. Traditionally, they are non-executable files with some pre-formatted text, used as the basis of a bazillion documents that can be generated with a computer program. I worked on a project where I had to write a program that would take a Microsoft Word template, containing parameters like $first, $name, $phone, and so on, and generate a specific Word document for every student in a school.

Web templating does something very similar. It uses a templating processor that takes data from a source of information, typically a database and a template, a generic HTML file with some kind of parameters inside. The processor then merges the data and template to generate a bunch of static web pages or dynamically generates HTML on the fly.

If you have been using PHP to create dynamic webpages, you will have been busy with web templating. Why? Because you have been inserting PHP code inside HTML files in between the <?php and ?> strings. Your templating processor was the Apache web server that has many additional roles. By the time your browser gets to see the result of your code, it is pure HTML. This makes this an example of server side templating. You could also use Ajax and PHP to transfer data in the JSON format and then have the browser process that data using JavaScript to create the HTML you need. Combine this with using templates and you will have client side templating.

Node.js

What Le Sacre du Printemps by Stravinsky did to the world of classical music, Node.js may have done to the world of web development. At its introduction, it shocked the world. By now, Node.js is considered by many as the coolest thing. Just like Le Sacre is a totally different kind of music—but by now every child who has seen Fantasia has heard it—Node.js is a different way of doing web development. Rather than writing an application and using a web server to soup up your code to a browser, the application and the web server are one and the same.

This may sound scary, but you should not worry as there is an entire community that developed modules you can obtain using the npm tool. Before showing you an example, I need to point out an extremely important feature of Node.js: the language in which you will write your web server and application is JavaScript. So Node.js gives you server side JavaScript.

Installing Node.js

How to install Node.js will be different, depending on your OS, but the result is the same everywhere. It gives you two programs: Node and npm.

npm

The node packaging manager (npm)is the tool that you use to look for and install modules. Each time you write code that needs a module, you will have to add a line like this in:

var module = require('module');

The module will have to be installed first, or the code will fail. This is how it is done:

npm install module 

or

npm -g install module 

The latter will attempt to install the module globally, the former, in the directory where the command is issued. It will typically install the module in a folder called node_modules.

node

The node program is the command to use to start your Node.js program, for example:

node myprogram.js

node will start and interpret your code. Type Ctrl-C to stop node. Now create a file myprogram.js containing the following text:

var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080');

So, if you installed Node.js and the required http module, typing node myprogram.js in a terminal window, your console will start up a web server. And, when you type http://localhost:8080 in a browser, you will see the world famous two word program example on your screen. This is the equivalent of getting the It works! thing, after testing your Apache web server installation.

As a matter of fact, if you go to http://localhost:8080/it/does/not/matterwhat, the same will appear. Not very useful maybe, but it is a web server.

Serving up static content

This does not work in a way we are used to. URLs typically point to a file (or a folder, in which case the server looks for an index.html file) , foo.html, or bar.php, and when present, it is served up to the client.

So what if we want to do this with Node.js? We will need a module. Several exist to do the job. We will use node-static in our example. But first we need to install it:

npm install node-static

In our app, we will now create not only a web server, but a fileserver as well. It will serve all the files in the local directory public. It is good to have all the so called static content together in a separate folder. These are basically all the files that will be served up to and interpreted by the client. As we will now end up with a mix of client code and server code, it is a good practice to separate them.

When you use the Express framework, you have an option to have Express create these things for you. So, here is a second, more complete, Node.js example, including all its static content.

hello.js, our node.js app

var http = require('http');
var static = require('node-static');
var fileServer = new static.Server('./public');
http.createServer(function (req, res) {
fileServer.serve(req,res);
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080');

hello.html is stored in ./public.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello world document</title>
<link href="./styles/hello.css" rel="stylesheet">
</head>
<body>
<h1>Hello, World</h1>
</body>
</html>

hello.css is stored in public/styles.

body {
background-color:#FFDEAD;
}
h1
{
color:teal;
margin-left:30px;
}
.bigbutton {
height:40px;
color: white;
background-color:teal;
margin-left:150px;
margin-top:50px;
padding:15 15 25 15;
font-size:18px;
}

So, if we now visit http://localhost:8080/hello, we will see our, by now too familiar, Hello World message with some basic styling, proving that our file server also delivered the CSS file.

You can easily take it one step further and add JavaScript and the jQuery library and put it in, for example, public/js/hello.js and public/js/jquery.js respectively.

Too many notes

With Node.js, you only install the modules that you need, so it does not include the kitchen sink by default! You will benefit from that for as far as performance goes.

Back in California, I have been a proud product manager of a PC UNIX product, and one of our coolest value-add was a tool, called kconfig, that would allow people to customize what would be inside the UNIX kernel, so that it would only contain what was needed. This is what Node.js reminds me of. And it is written in C, as was UNIX. Deja vu.

However, if we wanted our Node.js web server to do everything the Apache Web Server does, we would need a lot of modules. Our application code needs to be added to that as well. That means a lot of modules. Like the critics in the movie Amadeus said: Too many notes.

Express 4

A good way to get the job done with fewer notes is by using the Express framework. On the expressjs.com website, it is called a minimal and flexible Node.js web application framework, providing a robust set of features for building web applications.

This is a good way to describe what Express can do for you. It is minimal, so there is little overhead for the framework itself. It is flexible, so you can add just what you need. It gives a robust set of features, which means you do not have to create them yourselves, and they have been tested by an ever growing community.

But we need to get back to templating, so all we are going to do here is explain how to get Express, and give one example.

Installing Express

As Express is also a node module, we install it as such. In your project directory for your application, type:

npm install express

You will notice that a folder called express has been created inside node_modules, and inside that one, there is another collection of node-modules. These are examples of what is called middleware.

In the code example that follows, we assume app.js as the name of our JavaScript file, and app for the variable that you will use in that file for your instance of Express. This is for the sake of brevity. It would be better to use a string that matches your project name.

We will now use Express to rewrite the hello.js example. All static resources in the public directory can remain untouched. The only change is in the node app itself:

var express = require('express');
var path = require('path');
var app = express();
app.set('port', process.env.PORT || 3000);
var options = {
dotfiles: 'ignore',
extensions: ['htm', 'html'],
index: false
};
app.use(express.static(path.join(__dirname, 'public') ,
options ));
app.listen(app.get('port'), function () {
console.log('Hello express started on http://localhost:' +
app.get('port') + '; press Ctrl-C to terminate.' );
});

This code uses so called middleware (static) that is included with express. There is a lot more available from third parties.

Well, compared to our node.js example, it is about the same number of lines. But it looks a lot cleaner and it does more for us. You no longer need to explicitly include the HTTP module and other such things.

Templating and Express

We need to get back to templating now. Imagine all the JavaScript ecosystem we just described. Yes, we could still put our client JavaScript code in between the <script> tags but what about the server JavaScript code? There is no such thing as <?javascript ?> !

Node.js and Express, support several templating languages that allow you to separate layout and content, and which have the template system do the work of fetching the content and injecting it into the HTML.

The default templating processor for Express appears to be Jade, which uses its own, albeit more compact than HTML, language. Unfortunately, that would mean that you have to learn yet another syntax to produce something.

We propose to use handlebars.js. There are two reasons why we have chosen handlebars.js:

  • It uses <html> as the language
  • It is available on both the client and server side

Getting the handlebars module for Express

Several Express modules exist for handlebars. We happen to like the one with the surprising name express-handlebars. So, we install it, as follows:

npm install express-handlebars

Layouts

I almost called this section templating without templates as our first example will not use a parameter inside the templates. Most websites will consist of several pages, either static or dynamically generated ones. All these pages usually have common parts; a header and footer part, a navigation part or menu, and so on . This is the layout of our site. What distinguishes one page from another, usually, is some part in the body of the page where the home page has different information than the other pages. With express-handlebars, you can separate layout and content. We will start with a very simple example.

Inside your project folder that contains public, create a folder, views, with a subdirectory layout. Inside the layouts subfolder, create a file called main.handlebars. This is your default layout. Building on top of the previous example, have it say:

<!doctype html>
<html>
<head>
<title>Handlebars demo</title> </head>
<link href="./styles/hello.css" rel="stylesheet">
<body>
{{{body}}}
</body>
</html>

Notice the {{{body}}} part. This token will be replaced by HTML. Handlebars escapes HTML. If we want our HTML to stay intact, we use {{{ }}}, instead of {{ }}. Body is a reserved word for handlebars.

Create, in the folder views, a file called hello.handlebars with the following content. This will be one (of many) example of the HTML {{{body}}}, which will be replaced by:

<h1>Hello, World</h1>

Let’s create a few more june.handlebars with:

<h1>Hello, June Lake</h1>

And bodie.handlebars containing:

<h1>Hello, Bodie</h1>

Our first handlebars example

Now, create a file, handlehello.js, in the project folder. For convenience, we will keep the relevant code of the previous Express example:

var express = require('express');
var path = require('path');
var app = express();
var exphbs = require(‘express-handlebars’); app.engine('handlebars',
exphbs({defaultLayout: 'main'})); app.set('view engine', 'handlebars');
app.set('port', process.env.PORT || 3000);
var options = { dotfiles: 'ignore', etag: false,
extensions: ['htm', 'html'],
index: false
};
app.use(express.static(path.join(__dirname, 'public') , options  ));
app.get('/', function(req, res)
{
res.render('hello');   // this is the important part
});
app.get('/bodie', function(req, res)
{
res.render('bodie');
});
app.get('/june', function(req, res)
{
res.render('june');
});
app.listen(app.get('port'),  function () {
console.log('Hello express started on http://localhost:' +
app.get('port') + '; press Ctrl-C to terminate.' );
});

Everything that worked before still works, but if you type http://localhost:3000/, you will see a page with the layout from main.handlebars and {{{body}}} replaced by, you guessed it, the same Hello World with basic markup that looks the same as our hello.html example.

Let’s look at the new code. First, of course, we need to add a require statement for our express-handlebars module, giving us an instance of express-handlebars. The next two lines specify what the view engine is for this app and what the extension is that is used for the templates and layouts. We pass one option to express-handlebars, defaultLayout, setting the default layout to be main. This way, we could have different versions of our app with different layouts, for example, one using Bootstrap and another using Foundation.

The res.render calls determine which views need to be rendered, so if you type http:// localhost:3000/june, you will get Hello, June Lake, rather than Hello World. But this is not at all useful, as in this implementation, you still have a separate file for each Hello flavor. Let’s create a true template instead.

Templates

In the views folder, create a file, town.handlebars, with the following content:

{{!-- Our first template with tokens --}}
<h1>Hello, {{town}} </h1>

Please note the comment line. This is the syntax for a handlebars comment. You could HTML comments as well, of course, but the advantage of using handlebars comments is that it will not show up in the final output.

Next, add this to your JavaScript file:

app.get('/lee', function(req, res)
{
res.render('town', { town: "Lee Vining"});
});

Now, we have a template that we can use over and over again with different context, in this example, a different town name. All you have to do is pass a different second argument to the res.render call, and {{town}} in the template, will be replaced by the value of town in the object. In general, what is passed as the second argument is referred to as the context.

Helpers

The token can also be replaced by the output of a function. After all, this is JavaScript. In the context of handlebars, we call those helpers. You can write your own, or use some of the cool built-in ones, such as #if and #each.

#if/else

Let us update town.handlebars as follows:

{{#if town}}
<h1>Hello, {{town}} </h1>
{{else}}
<h1>Hello, World </h1>
{{/if}}

This should be self explanatory. If the variable town has a value, use it, if not, then show the world. Note that what comes after #if can only be something that is either true of false, zero or not. The helper does not support a construct such as #if x < y.

#each

A very useful built-in helper is #each, which allows you to walk through an array of things and generate HTML accordingly. This is an example of the code that could be inside your app and the template you could use in your view folder:

app.js code snippet

var californiapeople = {
   people: [
{“name":"Adams","first":"Ansel","profession":"photographer",
   "born"       :"SanFrancisco"},
{“name":"Muir","first":"John","profession":"naturalist",
   "born":"Scotland"},
{“name":"Schwarzenegger","first":"Arnold",
   "profession":"governator","born":"Germany"},
{“name":"Wellens","first":"Paul","profession":"author",
   "born":"Belgium"}
]   };
app.get('/californiapeople', function(req, res)
{
res.render('californiapeople', californiapeople);
});

template (californiapeople.handlebars)

<table class=“cooltable”>
{{#each people}}
   <tr><td>{{first}}</td><td>{{name}}</td>
   <td>{{profession}}</td></tr>
{{/each}}
</table>

Now we are well on our way to do some true templating. You can also write your own helpers, which is beyond the scope of an introductory article. However, before we leave you, there is one cool feature of handlebars you need to know about: partials.

Partials

In web development, where you dynamically generate HTML to be part of a web page, it is often the case that you repetitively need to do the same thing, albeit on a different page.

There is a cool feature in express-handlebars that allows you to do that very same thing: partials. Partials are templates you can refer to inside a template, using a special syntax and drastically shortening your code that way. The partials are stored in a separate folder. By default, that would be views/partials, but you can even use subfolders.

Let's redo the previous example but with a partial. So, our template is going to be extremely petite:

{{!-- people.handlebars inside views  --}}
   {{> peoplepartial }}

Notice the > sign; this is what indicates a partial. Now, here is the familiar looking partial template:

{{!-- peoplepartialhandlebars inside views/partials --}}
<h1>Famous California people </h1>
<table>
{{#each people}}
<tr><td>{{first}}</td><td>{{name}}</td>
<td>{{profession}}</td></tr>
{{/each}}
</table>

And, following is the JavaScript code that triggers it:

app.get('/people', function(req, res)
{
res.render('people', californiapeople);
});

So, we give it the same context but the view that is rendered is ridiculously simplistic, as there is a partial underneath that will take care of everything. Of course, these were all examples to demonstrate how handlebars and Express can work together really well, nothing more than that.

Summary

In this article, we talked about using templates in web development. Then, we zoomed in on using Node.js and Express, and introduced Handlebars.js. Handlebars.js is cool, as it lets you separate logic from layout and you can use it server-side (which is where we focused on), as well as client-side. Moreover, you will still be able to use HTML for your views and layouts, unlike with other templating processors.

For those of you new to Node.js, I compared it to what Le Sacre du Printemps was to music. To all of you, I recommend the recording by the Los Angeles Philharmonic and Esa-Pekka Salonen. I had season tickets for this guy and went to his inaugural concert with Mahler’s third symphony.

PHP had not been written yet, but this particular performance I had heard on the radio while on the road in California, and it was magnificent. Check it out. And, also check out Express and handlebars.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Practical Web Development

Explore Title