Handlebars Templates in Cloudflare Workers

These days, the most prevalent pattern for web development is to have one or more APIs and a Single Page Application (SPA) that coordinates calling these APIs and representing their output as HTML in a dynamic, client-side web application.

Especially with dedicated development frameworks and specialised build toolchains, this new approach is a great way to get to a result quickly and efficiently.

However, there is still a case to be made for server side rendered HTML. Indeed, newer frameworks like Vue and React offer a hybrid approach that lets you serve up parts of your HTML as interpreted on the server and made dynamic by rehydrating it on the client.

That's not what this article is about.

This article will demonstrate how to drag a somewhat old-school templating technology into a modern hosting stack: We're going to use Cloudflare's Workers to serve up Handlebars templates.

To do this we will take the following steps:

  • add a number of handlebars related dependencies to the Wrangler project;
  • add some scripts to your package.json; and
  • create a Custom build step in the wrangler.toml file

Constraints

Due to the set of technologies Cloudflare uses to make Workers possible, core Node modules are not available, including fs. Unfortunately, the full Handlebars engine uses it to load files from disk, disqualifying it from being used.

The runtime-only version of Handlebars on the other hand is smaller and does not rely on these Node packages.

The only prerequisite of using the Handlebars runtime-only version is that all templates must be precompiled. Our project needs to be extended with a Custom Build step in the wrangler.toml file.

Another constraint is that require-ing other files is not allowed without enabling the NodeJS compatibility layer, which will reduce performance of your Cloudflare Worker significantly.

For bonus points, we have also extended the registerHelper functionality of Handlebars to support asynchronous operations so that we can perform more complicated operations if we so desire.

Project folder structure

The rest of these instructions assume the following:

  • You have a views folder in the root of your project
  • It has two sub-folders called pages and partials.
  • You have an assets folder in the root of your project

Adding dependencies

Add the following dependencies to your package.json:

"handlebars": "^4.7.7",
"hbs-async-render": "^1.0.1"

And add this to your devDependencies section:

"hbs-import-transpile": "^1.0.4"

The handlebars module provides the Handlebars runtime-only environment. The hbs-async-render module allows us to register and succesfully evaluate Handlebars helpers that return Promises rather than content.

Lastly, we need the hbs-import-transpile for a compile-time file manipulation that will let us use the CommonJS output generated by the handlebars command line tool with import rather than require.

Adding package.json scripts

We are you going to add three new scripts to the package.json file.

The first calls the handlebars command-line tool. If you have not yet installed, please make sure you run the command below:

$ npm install -g handlebars

The second will take the output from the tool and transpile it for use as an import rather than require.

Lastly, we are adding another script target that can run these script in one go.

"handlebars": "npm run compilehbs && npm run transpilehbs && rm src/*-original.js",

"compilehbs": "handlebars -e hbs -f src/pages-original.js views/pages/ && handlebars -e hbs -p -f src/partials-original.js views/partials/",

"transpilehbs": "hbs-import-transpile src/pages-original.js > assets/pages.js && hbs-import-transpile src/partials-original.js > assets/partials.js"

The rm command in the handlebars target cleans up the output from compilehbs.

Updating wrangler.toml to run Custom Build step

Add the following to your wrangler.toml file to enable a custom build step that invokes the handlebars target from the package.json.

[build]
command="npm run handlebars"
watch_dir="views/"


Any time a file in the views/ folder is touched, your Worker will recompile the handlebars templates, the rest of the codebase, and deploy it to your function in the cloud.

Code Example

Now that we have configured out Cloudflare Workers project to precompile Handlebars templates, let's try creating some code with it.

You can find the Github Repository here: