Table of contents
1.
Introduction
2.
Getting started
3.
Pug
4.
Accessing variables
5.
Looping over arrays
6.
Rendering Pug templates in Express
7.
Adding partials
8.
Handlebars
9.
Rendering handlebars Templates with Express
10.
Adding partials
11.
EJS
12.
Rendering EJS Templates with Express
13.
Adding partials
14.
Nunjucks
15.
Rendering Nunjucks Templates with Express
16.
Adding Partials
17.
FAQs
18.
Key Takeaways
Last Updated: Mar 27, 2024

Template engines in Node.js

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

We all are familiar with how to build dynamic programming websites with APIs as modern-day web developers. Here, Node.js  works like a magic wand. It helps set up API backends quickly and also to get connected with client-side web applications. But, as you know the fact that Node provides another way of template engines for rendering web pages?

Sounds confusing, right. Let’s figure it out in more detail.

 

Getting started

Opposing the API-based web building approach, template engines enable to render pages with dynamic content on the server-side. Working with pages that rely on data retrieved from web pages is very flexible. One such example is the code reuse feature in template engines for improving the development process. 

 

The basic building block of a template engine-based website is the template. Each page template speaks about the basic structure of the web page, including correct syntax and variables. During the rendering of the page, exact values of the variables can be passed for creating a page. 

 

The commonly used template engines are:

  • Pug
  • EJS
  • Handlebars
  • Nunjacks
  • doT
  • Mustache
  • Underscore
  • marko

 

In this article, we will cover the first four of them: Pug, EJS, Handlebars, and Nunjacks. We will look at various examples to understand better working with template engines and building incredibly better web pages.

 

Pug

Also known as jade, and is one of the most used template engines in Node.js. The syntax of the pug is based on indentation. Multiple control structures can be used within the code, including conditional and loops. 

Below is the demonstration of the above-discussed concept:

 

doctype html 
html 
    head 
        meta(name='viewport', content='width=device-width')
        link(rel="stylesheet", href="https://cddn.jsddelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css")
        title Home Page
    body 
        div.navbar.navbar-expand.navbar-light.bg-warning
     ul.navbar-nav.mb-2
         li.nav-item
             a.nav-link(href="/") Home
         each field in fields 
             li.nav-item  
                 a.nav-link(href="/"+field_.names) #{field_.names}
 
        div.container.text-left.mt-3
            h1 Hello coders!! , #{user}
            div.message
                p How can we help you with our website.

 

We can note that using PUGs, HTML element names are used directly without enclosing tags in its syntax. Indentation is used to derive hierarchy in the following steps, where indented elements are children of the upper element.

 

The element of a class can also be added as a regular attribute. It provides the license to write javascript code for determining the value of the attribute. 

 

div(class=logged ? "logged" : "anon")

 

The URLs of the anchor tags are done similarly.

a(href="/"+field.name)

 

Accessing variables

Two variables, fields and user, are used in the Pug template for creating bug structure. The value accessing inside the template can happen in two ways:

The only content assigned to an Html element or attribute is the variable, then equal sign can be used to get our job done.

 

title=titlevar

 

Another way is to use #{var} syntax for accessing the variable value. Let’s see the below example to get a better idea about this:

 

h1 Welcome to Coding Ninjas, #{user}

 

Looping over arrays

Below is the demonstration of iterating over an array variable in the Pug template.

 

each field in fields 
    li.nav-item  
        a.nav-link(href="/"+field.name) #{field.name}

 

Rendering Pug templates in Express

It is one of the popular Node.js templates. Dedicated methods to introduce and include the usage of template engines on the server-side, both Express provides the things. For performing these operations, the Pug template is first put in the file with the .pug extension, further storing it in a directory named project folder. At first, we will give our file a name, let’s say index.pug. Then Pug needs to be installed using npm. The syntax to install the same is:

 

npm install pug

 

Now, the remaining part from the initial application code is done.

 

// App.js.

const express = require("express");
const path = require("path");

const app = express();

// Set view engine name and template directory path.
app.set("view engine""pug");
app.set("views", path.join(__dirname, "views"));

app.listen(3000 || process.env.PORT, () => {
    console.log("Server started listening");
});

 

Now, it’s time to render the index.pug file for requests coming to “/.” 

 

fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];

app.get("/", (req, res) => {
    const username = req.query.username;
    res.render("index", {user: username, fields: fields});
});

 

In the example above, variable values are passed as arguments to render the method. Doing so allows Pug to replace variable names with the actual names and helps to render the final Html content. 

 

Adding partials

This is one of the unique features which is used for reusing code snippets. Using partials, the reused components are declared separately and, on the other side, included in other templates.

In the example taken above, the component is the navbar which we can reuse for creating different components on the app. This saves a lot of time. Regardless of writing code many times, the same piece of code written inside a navbar can be reused.

 

// Views/navbar.pug

div.navbar.navbar-expand.navbar-light.bg-warning
    ul.navbar-nav.mb-2
        li.nav-item
            a.nav-link(href="/") Home
        each field in fields 
            li.nav-item  
                a.nav-link(href="/"+field.name) #{field.name}

Using the partial in out template is very simple just like including a special keyword named “include”. 

 

//views/index.pug 

body 
  include navbar
  div.container.text-left.mt-3
      h1 Welcome to our website, #{user}
      div.message
          p Find anything you want on our website.

 

Handlebars

It is another extension of the template engine in Node, Mustache. Both Mustache and Handlebars differentiate themselves from Pug. Both Mustache and Handlebars are logic-less template engines. They do not support They do not support Logic-based conditionals or template code loops. The codebase is easier to test and maintain as it encourages to separate the logic from the presentation page.

 

Instead of depending on the indentation, Handlebars uses regular Html syntax. 

 

{{!-- views/index.hbs --}}

<!DOCTYPE html>
<html>
<head>
    <meta name='viewport', content='width=device-width'/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
    <title>Home Page</title>
</head>
<body>
    <div class="navbar navbar-expand navbar-light bg-warning">
        <ul class="navbar-nav mb-2">
            <li class="nav-item">
                <a class="nav-link" href="/">Home</a>
            </li>
            {{#each fields}}
                <li class="nav-item">
                    <a class="nav-link" href="/{{name}}">{{name}}</a>
                </li>
            {{/each}}
        </ul>
    </div>
    <div class="container text-left mt-3">
        <h1>Welcome to our website, {{user}}</h1>
        <div class="message">
            <p>Find anything you want on our website.</p>
        </div>
    </div>
</body>
</html>

 

In the example given above, we are creating a page with the same content as the Handlebars syntax. Since the syntax of Handlebars is quite similar to Html, it’s very intuitive to use them. For accessing the variables in Handlebars, variable names should be enclosed in two brackets.

 

<h1>Welcome to our website, {{user}}</h1>

 

Using handlebars, we can also travel throughout the array. Below is the syntax for the same:

 

{{#each fields}}
    <li class="nav-item">
        <a class="nav-link" href="/{{name}}">{{name}}</a>
    </li>
{{/each}}

 

Here, we can directly access the properties of each object of the array.

 

Rendering handlebars Templates with Express

For using handlebars with the express, we should install it first with npm. 

 

npm install hbs

Then the handlebars are set up as the view engine, and the Pug steps are repeated for the rendering template.

 

//app.js

const express = require("express");
const path = require("path");

const app = express();

app.set("view engine""hbs");
app.set("views", path.join(__dirname, "views"));

fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];

app.get("/", (req, res) => {
    const username = req.query.username;
    res.render("index", {user: username, fields: fields});
});

app.listen(3000 || process.env.PORT, () => {
    console.log("Server started listening");
});

 

Adding partials

Unlike handlebars, the partials should be registered first. This step is followed first before using them inside a template. But, in the case of partials, a separate directory is first created inside the views directory, which is used for storing partial files.

The code for the navbar component can be added inside the partials directory.

 

{{! views/partials/navbar.hbs}}

<div class="navbar navbar-expand navbar-light bg-warning">
    <ul class="navbar-nav mb-2">
        <li class="nav-item">
            <a class="nav-link" href="/">Home</a>
        </li>
        {{#each field}}
            <li class="nav-item">
                <a class="nav-link" href="/{{name}}">{{name}}</a>
            </li>
        {{/each}}
    </ul>
</div>

 

In the next step, the partial directory can be registered inside the application code.

const hbs = require("hbs");
hbs.registerPartials(path.join(__dirname, "views/partials"));

 

Now, as we have included the partial component of the template, the work of handlebars starts from there. It will identify it and will import the component code for rendering the web page.

 

<body>
    {{>navbar}} {{! including the partial}}
    <div class="container text-left mt-3">
        <h1>Welcome to our website, {{user}}</h1>
        <div class="message">
            <p>Find anything you want on our website.</p>
        </div>
    </div>
</body>

 

EJS

EJS is one of the popular templates in Node.js. It uses the same Html-like structure. Plain javascript can be used with variables and programming logic inside its template to control its structure.

The EJS provides a set of tags for javascript code in a template. The final rendered output has some effects which are determined by each unique tag. Following are some of the commonly used tags:

 

  • <%: This tag determines the flow control of any program code using conditionals, loops, etc. But, no output is provided by it.

 

  • <%=: it gives the calculated value inside any template. Generally, Html code is escaped by this tag.

 

  •  <%-: Any unescaped value is printed by this tag.

 

  • <%#: this is for a comment tag.

 

Now, let’s figure out how to convert the Node application’s home page into an EJS template:

 

<html>
<head>
    <meta name='viewport', content='width=device-width'/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
    <title>Home Page</title>
</head>
<body>
    <div class="navbar navbar-expand navbar-light bg-warning">
        <ul class="navbar-nav mb-2">
            <li class="nav-item">
                <a class="nav-link" href="/">Home</a>
            </li>
            <% fields.forEach(field => { %>
                <li class="nav-item">
                    <a class="nav-link" href=<%= "/"+ field.name %>><%= field.name %></a>
                </li>
            <% }) %>
        </ul>
    </div>
    <div class="container text-left mt-3">
        <h1>Welcome to our website, <%= user %></h1>
        <div class="message">
            <p>Find anything you want on our website.</p>
        </div>
    </div>
</body>
</html>

 

In the example given above, EJS is using the basic template to build the basic template. Then everything(accessing variables to iterate through arrays) is done and maintained by using regular javascript code declared inside the special tags. The special tags we have already seen above. 

 

Rendering EJS Templates with Express

This rendering also follows the same steps as we did before. First, EJS is installed using npm. 

 

npm install ejs

 

In the next steps, EJS is set up as the application’s view engine, which will render index.ejs with variable values. This step is performed before sending it to the client.

 

const express = require("express");
const path = require("path");

const app = express();

app.set("view engine""ejs");
app.set("views", path.join(__dirname, "views"));

fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];

app.get("/", (req, res) => {
    const username = req.query.username;
    res.render("index", {user: username, fields: fields});
});

app.listen(3000 || process.env.PORT, () => {
    console.log("Server started listening");
});

 

Adding partials

This step follows the exact same steps as we did in the case of Pug. a new partials file is created first, views/partials/navbar.ejs with navbar code. Hence, the partial can be concluded as:

 

<body>
    <%- include ("partials/navbar") %>

    <div class="container text-left mt-3">
        <h1>Welcome to our website, <%= user %></h1>
        <div class="message">
            <p>Find anything you want on our website.</p>
        </div>
    </div>
</body>

 

Nunjucks

It is one of the powerful engines built with Mozilla that can be used with Node.js. Nunjucks support asynchronous loading of content during the rendering of web pages.  The Html syntax is very similar to Handlebars and EJS. The control operations are performed by a special {% %} tag.

<!DOCTYPE html>
<html>
<head>
    <meta name='viewport', content='width=device-width'/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
    <title>Home Page</title>
</head>
<body>
    <div class="navbar navbar-expand navbar-light bg-warning">
        <ul class="navbar-nav mb-2">
            <li class="nav-item">
                <a class="nav-link" href="/">Home</a>
            </li>
            {% for field in fields %}
                <li class="nav-item">
                    <a class="nav-link" href="/{{field.name}}">{{field.name}}</a>
                </li>
            {% endfor %}
        </ul>
    </div>
    <div class="container text-left mt-3">
        <h1>Welcome to our website, {{ user }}</h1>
        <div class="message">
            <p>Find anything you want on our website.</p>
        </div>
    </div>
</body>
</html>

 

In the code snippet given above, variables can be accessed by Nunjucks by double brackets. For performing control operations like conditionals, loops, etc., we use {% %} tags.

 

Rendering Nunjucks Templates with Express

The first step is the same as we did before. The Nunjucks can be installed by using npm.

 

npm install nunjucks

 

But the way to render templates using Nunjucks is a little different from what we did before. Let’s figure it out in detail. 

For rendering using Nunjucks, a Nunjucks configuration step is followed for setting up the view engines and rendering the web pages. 

 

const express = require("express");
const path = require("path");
const nunjucks = require("nunjucks");

const app = express();

app.set('view engine''njk');

//configure Nunjucks bypassing the express app and setting auto escape to true
nunjucks.configure('views', {
    Auto escape:  true,
    express:  app
})

fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];

app.get("/", (req, res) => {
    const username = req.query.username;
    res.render("index", {user: username, fields: fields});
});

app.listen(3000 || process.env.PORT, () => {
    console.log("Server started listening");
});

 

Adding Partials

The addition of partials is done similarly as we did in the previous cases. First, the navbar code is added in a file called “navbar.njk”. After this step, the partials can be added to the homepage template using the include keyword.

 

<body>
    {% include "partials/navbar.njk" %}
    <div class="container text-left mt-3">
        <h1>Welcome to our website, {{ user }}</h1>
        <div class="message">
            <p>Search and start coding.</p>
        </div>
    </div>
</body>

 

FAQs

  1. Name the engine which is used by Node js?
    V8 Javascript Engine is the engine which is used by Node js.
     
  2. Can node JS die?
    No, the node JS can never die even if the type has stabilized a little over the years. As it’s working beyond 2021, it’s still the same and will keep working as it is.
     
  3. Is it beneficial to use template engines?
    Actually, we don’t need template engines but using them is beneficial as it transforms out page to more dynamic.

Key Takeaways

In this article, we begin our discussion about using template engines using Node.js for building web applications. We have talked about them with the help of various examples. I hope this article gives a decent introduction to how to work with templates. 

Keeping the theoretical knowledge at our fingertips helps us get about half the work done. To gain complete understanding, practice is a must. To gain a thorough understanding, visit our page.

 

Live masterclass