Menu

Dust.js Templates

3 min read February 6, 2017 at 11:06am on Rebuilding Postleaf

The Problem with Handlebars

The first version of Postleaf used templates powered by a PHP variation of Handlebars. I chose Handlebars because the syntax is very simple to learn and understand.

Hello, {{name}}!

There is, however, one fundamental feature of Handlebars that users tend to find confusing: helpers can have both parameters and arguments.

{{helper param1 param2 arg1="value" arg2="value"}}

Parameters are unnamed, ordered values that get passed in to helpers, whereas arguments are named, unordered values that get passed in. You can probably see how this can start to get confusing when you mix them together. (Of course, this could be solved by convention, but I prefer more structure when possible.)

Another issue with Handlebars is the lack of support for asynchronous helpers. The development team doesn't seem to agree with the many use cases, but it's a necessity for Postleaf.

Without this feature, you wouldn't be able to fetch resources outside of the provided context. For example, if you wanted to fetch five related posts in your template, those five posts would have to be provided to the template before it's rendered. You wouldn't be able to do this:

{{related_posts count="5"}}
...
{{/related_posts}}

It's must easier incorporate this functionality into a template rather than through a controller, so I started looking for alternatives.

Note: This wasn't an issue with the PHP variation of Handlebars because PHP is a synchronous language, but it's a devastating problem to have in JavaScript.

Introducing Dust.js

Dust.js is a powerful, modern template system maintained by the folks at LinkedIn. It's familiar, elegant, and just as easy to use as Handlebars.

Hello, {name}!

Helpers only support attributes, simplifying the helper API quite a bit:

{@helper arg1="value" arg2="value"/}

You'll notice the syntax is a bit different than Handlebars, but those minor differences make your templates so much easier to read once you know what they do.

Dust also supports filters, which can be really useful. For example, you can turn off HTML encoding by piping a variable like this:

{content|s}

I've already added custom filters for converting Markdown to HTML and HTML to text. They're really easy to use:

{author.bio|markdownToHtml}
{content|htmlToText}

And, of course, Dust supports asynchronous helpers so you can fetch data from your own helpers — even if they return a promise!

Here's a quick comparison of Handlebars and Dust:

handlebars-dust-comparison.png

This isn't intended to be a full introduction to Dust. I'm just explaining why I decided to use it instead of Handlebars, and these are some of the most obvious examples.

Once you start using Dust in your own themes, I'm sure the benefits will become much more obvious!