Templating Engine for HTML (special case AMP)

I’m usually working with Angular. But recently I started an AMP Project (www.tsmean.com). For those of you who don’t know AMP, it’s short for “Accelerated Mobile Pages” where you use only the “Official AMP JavaScript Libraries” but no JavaScript of your own and only prerendered HTML. The goal of this is to make webpages blazingly fast. Since a requirement is precompiled html I can’t use Angular as a templating engine since that dynamically compiles the html. Even though it has a static option with Angular Universal (don’t get me started on this…), the Angular Universal rendered page still includes JavaScript so it’s not possible to render an AMP compatible (=JavaScript-free) page with it.

So I’m kind of back in the “dark ages” where I’m stuck with templating engines such as Mustache, Handlebars, EJS or Pug (former Jade). Why I need a templating engine should be obvious: I don’t want to copy / paste code snippets all around and duplicate them like crazy. So I need a templating engine. Just which one’s right? So I set out to choose my templating engine for html. Which has been an absolute nightmare. Let’s review our options.

Mustache

Mustache, we’ve all heard of it. Logic-less templating. So the entry point to the “mustache experience” is this one: https://mustache.github.io/

Since mustache is basically just a spec, it can be implemented in any language. That’s why you see so many languages there. I first clicked on the node.js link which leads to this godforsaken project I’ve used now for a quarter year: https://github.com/raycmorgan/Mu

The owner of the repo doesn’t seem to give two sh*ts about it. Last commit somewhen in 2016. Four unmerged pull requests https://github.com/raycmorgan/Mu/pulls. One of them is mine. No response whatsover.

Then I tried the one when clicking on “JavaScript” in mustache:  https://github.com/janl/mustache.js . Aha, that seems to be the right one with 11k github stars! Okay, I can’t concentrate because of that gif with the dude with the mustache. Is it just me, or is it really annoying to put that gif there? Maybe I’m just having a bad day. But then again, the command line tool also doesn’t seem to be ideal for me because I have to specify all used partials:

mustache -p path/to/partial1.mustache -p path/to/partial2.mustache dataView.json myTemplate.mustache

Can someone explain to me why this is necessary? The partials are already specified in the template! The first mustache compiler I mentioned didn’t require me to pass in all partials at compile time. I mean my template.mustache looks like this:

blabla
{{ > path/to/partial.html }}
blablub

Why do I have to pass this partial as a compiler option again? Especially if you have many views with many partials this becomes very tedious. And if the partial uses another partial? How am I supposed to track the usage of my partials? Unless … I don’t track it and just include all my partials everywhere. Then I’ll just have to register them ONCE in a single file, which is okay.

For those of you coming from Angular like myself, you’ll ask how can I pass data to partials?! You’d expect a syntax like

{{> mybutton title="Cancel" }}
{{> mybutton title="Save" }}

but this doesn’t exist. Instead you’ll set the variable inside the partial by the context you surround it with. An example:

{{#buttonOne}}
  {{> mybutton}}
{{/buttonOne}}
{{#buttonTwo}}
  {{> mybutton}}
{{/buttonTwo}}

and in the data.json you’d specify

{
  "buttonOne": {
    "title": "Cancel"
  },
  "buttonTwo": {
    "title": "Save"
  }
}

In the partial there could be the code

<button class="my-cool-button">{{title}}</button>

The result would print

<button class="my-cool-button">Cancel</button>
<button class="my-cool-button">Save</button>

It’s a bit of a change a first, but workable.

On a sidenote, there’s another small issue problem with the command line tool. The doc’s state:

The command line tool is basically a wrapper around Mustache.render so you get all the features.

But then their example is actually a demonstration that this doesn’t work:

var view = {
  title: "Joe",
  calc: function () {
    return 2 + 4;
  }
};

var output = Mustache.render("{{title}} spends {{calc}}", view);

where the view object is what’s supposed to go to  dataView.json (see above) which is obviously not possible since a JSON can’t hold a function value…

Handlebars

Remember how I said my project can’t have any extra JavaScript libraries? Now, the precompilation of handlebars seems to be so stupid, that it still requires a JavaScript library on runtime:

<script src="/libs/handlebars.runtime.js"></script>

Duuuudes, come on, you’re killin me…

Pug

Since the name “Jade” was copyright infringement, they changed it to pug. In case you don’t know it, it’s a html templating engine, that doesn’t look like html at all. It’s whitespace sensitive and you’ll have to learn a new language. For me, I don’t like it that they deviated so much from the standard html for a couple of reasons:

  • No copy / pasting of code snippets from nowhere (one might say that’s a actually a good thing…)
  • You’ll have to learn a “new language”
  • All team members will have to learn a new language.
  • Larger chance of getting out of fashion than when sticking with something similar to html like mustache (yet small chance, since it’s been here for a while and has too many users to be completely abandoned)
  • I don’t really find the whitespace based syntax better
  • My IDE doesn’t do it’s job as well

So all in all I have very little incentive to use pug, I just see a point of deviating that much from HTML.

EJS

EJS has horribly little documentation: http://ejs.co/

It doesn’t seem to be what I’m looking for: A command line tool to precompile some html templates. Rather you put your html as strings into into JavaScript files, which neither me nor my IDE like very much. As for storing html snippets in a separate file, then requiring them through JS, then paring to a string, and then storing that string again in a file, that’s just too complicated.

Conclusion

Mustache is the winner. Clean syntax that integrates well with html. Large community supporting it. Been here for a while. Not going anywhere anytime soon. Once you get it, you got it. However, it took me a while getting it, since the approach to handling templates and data seems weird when you come from Angular. This article on “passing variables to partials” has been a bit of an eyeopener for me, so thanks Pawel!

Leave a Reply

Your email address will not be published.