This tutorial is compatible with hapi v17. Node and Hapi should be installed for work with this tutorial.
In Hapi we can use different template engines to achieve dynamic HTML with dynamic data. One of this engines - Handlebars. In this tutorial we will learn how to use handlebars with Hapi framework.
Let’s start our work from creating a basic server in index.js
file:
'use strict';
const Hapi = require('hapi');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
const init = async () => {
server.route({
method: 'GET',
path: '/index',
handler: (req, h) => {
return "Hi!"
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
Hapi provides Vision plugin to work with template engines. It adds additional methods to h
response object. We should install it using the NPM or YARN:
npm i vision -s // or
yarn add vision
To use Handlebars we can install it using the next command:
npm i hbs -s // or
yarn add hbs
To start work with handlebars, we have to require the Handlebars and Vision module:
const Vision = require('vision');
const hbs = require('hbs');
Now, let’s notify Hapi server, that we will use the Handlebars as a default template engine for our server. Using the server.views()
method we can say to server, what template engine we have to use and where our templates should be located. Change the init()
****method inside index.js
to the following:
'use strict';
const Hapi = require('hapi');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
const init = async () => {
await server.register(Vision);
server.views({
engines: {
html: hbs
},
relativeTo: __dirname,
path: 'templates'
});
server.route({
method: 'GET',
path: '/index',
handler: (req, h) => {
return "Hi!"
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
We successfully registered handlebars as a default view engine for our Hapi server and told our server that templates are in templates
folder (it should be on same level as index.js
).
Go to your project folder and create a templates
directory. Put an index.html
template file in the templates/
folder:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{message}}
</div>
</div>
</body>
</html>
As you see, we created some variables in our index.html
- the title
and message
. We will interpolate these variables inside GET /index
route. Hapi framework provides two ways for rendering a view.
In this case, we can use the view
method of Vision module inside the h
object. The first argument it’s the name of our template, the second argument - the data for interpolation in selected template.GET /index
route should look like this:
server.route({
method: 'GET',
path: '/index',
handler: (req, h) => {
return h.view('index', {
title: 'Using handlebars in Hapi',
message: 'Tutorial'
});
}
});
In previous case, we can add additional logic/code inside handler
function. If we only need to render template and nothing extra, we can change the handler
from function to object and pass the view
parameter. It’s called “view handler” and should look like this:
server.route({
method: 'GET',
path: '/index',
handler: {
view: {
template: 'index',
context: {
title: 'Using handlebars in Hapi',
message: 'Tutorial'
}
}
}
});
To make “view handler” works you need to install the Inert module, require and register it in index.js
.
'use strict';
const Hapi = require('hapi');
const Vision = require('vision');
const hbs = require('hbs');
const Inert = require('inert');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
const init = async () => {
await server.register(Inert);
await server.register(Vision);
server.views({
engines: {
html: hbs
},
relativeTo: __dirname,
path: 'templates'
});
// you need to leave only one route - view handler OR h.view, because its reproduces a conflict
// view handler
server.route({
method: 'GET',
path: '/index',
handler: {
view: {
template: 'index',
context: {
title: 'Using handlebars in Hapi',
message: 'Tutorial'
}
}
}
});
// h.view
server.route({
method: 'GET',
path: '/index',
handler: (req, h) => {
return h.view('index', {
title: 'Using handlebars in Hapi',
message: 'Tutorial'
});
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
More information about View in Hapi: https://hapijs.com/tutorials/views
Learning Hapi.js? Buy my Hapi.js Handbook🔥
comments powered by Disqus