Getting Started with the Handlebars.js in Nodejs
Implementing the templating engine as a server-rendered website. Maximizing performance, workflow, and maintenance.
Why Take This Approach?
Server-Rendered Handlebars offers several benefits over the standard approaches: increased performance, site maintainable, and ease of integration.
Standard front-end development by nature encounters significant maintainability problems as it continues to grow and expand(as every website does over time).
Oftentimes common components are created several times per web page, or spread amongst several pages; text becomes hard to find, update and test. These decrease deployment confidence and increase the probability of inconsistencies, security bugs, or design glitches.
On the other hand, utilizing a standard CMS while beneficial comes with significant technical debt and commitment.
A server-rendered templating engine, like Handlebars, allows you to bypass all of these issues. Both in performance, long-term maintainability, and CMS integration.
We’ll be covering all of the above topics later on. All the way from maximizing performance, to maintainable architecture, to integrate your website with a Headless CMS. But for now, we’ll focus on developing a basic website with Handlebars and Nodejs.
And while you could use GatsbyJS to implement a performant website utilizing React, taking that route does limit you(though I would recommend it if you’re already using a traditional CMS or don’t need super high performance). But the framework requirement both for React and GraphQL, as well as it’s predefined architecture, are significant drawbacks.
Even still nothing will be faster than server-rendered Framework-less web pages. Feel free to test out every item in Gatsby's website with https://web.dev, though the fastest possible React can provide, the TtI and First CPU Idle are still at least 5 seconds(though it must be noted that usually, the time till first meaningful render is usually really low)
Overview
The Handlebars Templating Engine, which is based on the Mustache Templating Engine, serves as a way to design and develop DRY websites. Allowing for easier long-term maintainability, debugging, and expansion. While both handlebars and mustache can be used purely on the frontend and using gulp to compile to their HTML counterparts.
Taking the server-side rendered approach not only increases performance but also opens the possibility of integrating a Headless CMS (Like Strapi) with the backend, allowing significantly easier management.
In the future we’ll expand on this project, implementing a strong development workflow using sass, gulp. An efficient deployment setup using Nginx and docker. And finally connecting the website to a Headless CMS using MongoDB.
But for now, we’ll focus on setting the foundations of the Nodejs backend, and handlebars templating.
Prerequisites
- Git & Node installed on your computer.
- Basic Understanding of Server Languages(Node, PHP, Ruby, Java, etc). If you haven’t used them that’s alright, you can still follow along and if you get stuck either post a comment below or look for help in stackoverflow.com
- A Text Editor (I recommend VS Code)
Folder Structure
Here’s the general folder structure that we’ll be using. The specific files will be detailed as we go forward, and the project structure will change and expand as we add more functionality to the application.
node_modules/
public/
src/
scss/
server/
views/
partials/
.gitignore
gulpfile.js
package.json
To get started run the following commands on your preferred starting directory or create the folder structure manually.
mkdir handlebarsProject
cd handlebarsProject
If you have experience with Nodejs apps then simply set them up and skip to “Nodejs Backend: Foundations”.
Then use your favorite text editor/IDE. To open up the application folder. Once you have that handled, run the following commands to set up the basic foundations:
git init #creates git repo
npm init #sets up the package manager for the website(press yes for everything)
npm install express --save # web server framework to use with node
npm install nodemon --save-dev # makes development easier on node
npm install hbs --save # handlebars library for node
After that make sure to that a ‘start’ and a ‘dev’ script to your package.json. After all of the above, your package.json should look like this:
Note: Make sure create a .gitignore file with ‘node_modules/’ in it. We don’t want to include the dependencies in the version control.
Nodejs Backend: Foundations
Now let’s get started on the backend.
First, we’ll want to create a standard Express web server and create a route to the home page URL. From each express route, the response will render our predefined handlebars file, we’ll also configure any page specific data to populate the page later on.
To make sure express can find our handlebars files, we’ll have to register our views directory in express. As well as set the view engine in express.
const partialPath = path.join(__dirname, '../views/partials')const viewPath = path.join(__dirname, '../views')
These are the paths which we’ll use to register both the view path, which will point to the general page template’s we’ll be able to utilize. As well our partials path, which are generic components we could reuse in any template page.
hbs.registerPartials(partialPath)app.set('view engine', 'hbs')app.set('views', viewPath)
In order to configure express to properly render a templating engine(not just handlebars), you have to configure it to handle them specifically. Here we both register the partial path, so we can use every partial in the directory amongst our template pages, and then configure express’s view engine to work with HBS.
app.get('/', (req, res) => {console.log('RENDERING THE HOME PAGE')res.render('home.hbs') // express looks for a file in the views directory,//then compiles and renders them to the client})
We then create a standard Express Route to handle the base URL. Once a browser requests it, express will compile and serve render-ready HTML file. Later on, we’ll send more parameters to the render response, to further populate the page.
You can start up the server in production by running ‘npm run start’ or for development by running ‘npm run dev’. We have yet to create our handlebars views so nothing will be rendering for now.
Moving to the Front-End
Let’s Get Started With Handlebars!
We’ll develop basic templating pages, refactor appropriate components into partials and then create “contexts” for our pages in order to properly populate the pages with information.
Home Page
In the views directory, create a file named home.hbs. Then write the basic HTML shown below. This is the basic HTML code which we’ll refactor to use the functionality provided by handlebars.
If you start up the server and head to localhost:8080 you’ll notice that our pages are looking a little bland, and definitely not what we want. In the public directory add a CSS folder. There create a file named main.css.
If you run ‘npm run dev’ and go to localhost:8080. You should get something that looks like this.
The issue is that at the moment we aren’t using any of handlebar’s great features! It’s just a basic HTML page.
Let’s start by refactoring the parts that need to be reused into partials. Any component that we separate into our partial directory can be used from any handlebars template like this:
{{> partialName}}
Express will look for the partials in the directory we specified. Which in this case is ‘views/partials/’. Let’s get started by creating our partials files and refactoring the necessary code. For now, create two files in the partials directory named ‘header.hbs’ and ‘footer.hbs’ and copy/paste the header and footer tag into those files respectively.
So now, your home.hbs will look more like this:
Much easier to view, organize and update. Let’s create the templates for the other two pages in the header.
Create two more templates, about.hbs and more.hbs. And set them up in a similar way to our current home.hbs.
Now let’s update our header partial to properly route between pages by adding a <a> link tag within the <li> tag that represents each nav item. Furthermore, we also need to add the necessary express routes to make sure the pages get served.
So now we have several templates that are using partials as independent components. This helps keeps our template pages DRY.
The issue now is that all our pages look the same. And while we could change the text on each page, that defeats the point of using a templating language. We’ll use a cleaner way to customize the content we’re displaying on each page.
Enter Contexts
Handlebar contexts allow us to maintain page content, such as text, images, videos, lists, etc on the server side. Allowing us to develop templates generally, and then customizing them using contexts. This is also what will eventually allow us to hook up our server to a Headless CMS for easy management and expansion.
Let’s start by replacing the page title from:
<h1 class="title">Hello World</h1>
To:
<h1 class=“title”>Hello {{pageName}}</h1>
Handlebars.js uses the {{contextName}} in order to determine which string literal it should use out of the ones provided by the server. Now we simply need to provide the context on the backend, which can be provided as a JSON to the res.render() response we provide on the server.
So we would refactor our express routes to look like this:
app.get("/", (req, res) => { console.log("RENDERING THE HOME PAGE"); res.render("home.hbs", { pageName: "Home Page" });});
Make sure to update the other express routes in a similar manner. And now you should be able to easily differentiate between each page since they’ll all have their own custom titles.
Wrapping it Up
So far we’ve configured an express server to server handlebars templates, create 3-page templates which utilize partials and contexts to keep our pages DRY and readable.
We’ll stop for now, and continue on the next article focusing on more advance handlebars patterns such as conditional components, for-loops, and helper functions. Expanding on our pages, and refactoring our backend to increase maintainability and expandability.
Conclusion
Congrats on your brand new server-rendered, handlebars-based, site! As we continue on expanding upon it, you’ll see why view engines like Handlebars are an absolute must-have tool for any web developer.
If you want to look a little deeper, check out Handlebar’s documentation or the source code for this tutorial. Hope you have a great day!