JavaScript template libraries
For the last 3 months I’ve been working on a new web application at work. It’s quite unique in some regards, from the architecture perspective; the biggest difference from other projects that I’ve worked on is that almost entire page is one huge embeddable “widget”. This requires a completely different approach than I usually use:
- a lot of the code above the model layer is moved to the client side (i.e. JavaScript); this means that controllers and helpers are rather simple, controllers mainly return JSON, and there’s quite a lot of JavaScript to write
- since a significant part of the system is written in JavaScript, it needs to be unit-tested too
- I have to be very careful not to cause any JS, CSS or DOM id conflicts between the embedding site and the “widget“ (which includes such things as keeping all JS code in a single global namespace, and using jQuery in the “noConflict extreme“ mode through an alias)
Another thing, which I’d like to write about today, is the way the views were implemented in this project. Since entire GUI is created dynamically by JavaScript, I had basically two options:
- render the views in Rails with ERB and send big chunks of HTML via AJAX to JavaScript;
- or make Rails send only data as JSON, and render the views on the JavaScript side.
For performance reasons, the second solution is obviously much better. All static content can be cached, and after that we only need to send JSON data, which takes at least an order of magnitude less bandwidth than the rendered HTML. But this meant I needed to find a templating library for JavaScript to replace ERB. I had used the Template class from Prototype before, but that was only useful for one-line templates; I needed something more serious… Besides, I’m using jQuery here.
And actually I didn’t want to replace ERB completely. There are some things which shouldn’t be written literally in the template, but which aren’t part of the JSON data – things like constants, global project settings, etc. So I wanted the template files to be hybrid, containing both ERB and JavaScript tags; they would be first preprocessed by ERB (once per release), and JavaScript would fill the rest of the blanks.
So I fired up Google and started exploring. Here’s what I found:
jTemplates
{#foreach $T.records as record} <tr> <td><a href="/{$T.record.id}">{$T.record.name}</a></td> <td>{$T.record.description}</td> {#if $T.record.tags} <td>{$T.record.tags}</td> {#/if} </tr> {#/foreach}
This is the library that I’ve chosen in the end. It’s based on jQuery, syntax looks very clean, and it seems to be actively developed. It has a lot of extra features – for and for-each loops, if/else, includes, and so on; this may not be necessary for one-liners which update a single entry in a list, but it’s extremely important here, where the whole GUI is based on those templates. Also, it has a syntax that’s impossible to confuse with ERB.
I’ve written dozens of templates so far using this library, and I’m really content with it. If you’re using jQuery and you need to create a whole site with JavaScript templates, this one is for you.
JSRepeater
<tr context="records"> <td><a href="/${id}">${name}</a></td> <td>${description}</td> </tr>
JSRepeater is quite similar to jTemplates; it also uses jQuery, and has a similar syntax. However, it doesn’t have as many control structures as jTemplates, and they’re implemented in a different way. Instead of explicitly writing “foreach“, you add context=“…” attributes to the template HTML. I personally hate adding not existing attributes to HTML elements…
Another difference is that in jTemplates you can supply the template code in any way (you can just pass it as a string in a parameter to a function call), while JSRepeater expects the template to be already present inside the target container. E.g. you have a <div>
which contains a template, you run a function on it and the contents are processed so that it contains a rendered template. This could work in simple cases, but it would be too inconvenient in my project.
PURE
<tr class="record"> <td class="name">Name</td> <td class="description">Description</td> </tr>
PURE is framework-independent, so it can work with jQuery too. It has some advanced features, like iterating over a list of records, but I didn’t like the idea of marking fields using CSS classes. It seems a bit limiting (for example, I have no idea how to fill a link’s href this way), and it forces you to add a lot of classes to your elements which you otherwise wouldn’t add, which means that it has influence on how the final HTML looks like.
There’s also another library called NoTemplate, which is only for jQuery and has an almost identical syntax to PURE.
EJS (Embedded JavaScript)
<% for (var i=0; i<records.length; i++) { %> <tr> <td> <a href="/<%= records[i].id %>"><%= records[i].name %></a> </td> <td><%= records[i].description %></td> </tr> <% } %>
EJS looks exactly like ERB; and it’s not an accident, it’s actually a port of ERB. It has partials, helpers with names like text_field_tag, and you can write any JS code in <% %> blocks in the same way you write Ruby code in ERB. All of this sounds great, especially in a Rails application, but as I said, I wanted the syntax to be different than ERB’s to be able to use both of them in one file. If you don’t have such requirement, and you’re writing a Rails application, EJS looks like an excellent choice.
Trimpath templates
{for record in records} <tr> <td><a href="/${record.id}">${record.name}</a></td> <td>${record.description}</td> </tr> {/for}
Syntax looks nice, it has a lot of features, but the API seems a bit complicated, and it looks like the library hasn’t been updated for ages (specifically, since 2005 :). Also, it expects you to put the template text inside a <textarea>
somewhere on the page… which is kind of inconvenient.
Other libraries
I’ve found several other libraries, but they were all either too simple (just variable substitution, without any ifs and fors) or just not suitable for me for some reason. Here are some links in case you’re interested:
- jQuery Templates – too simple for me
- jquery-simple-templates – too simple (as the name suggests… :)
- ExtJS framework, contains a template class – not free
- Tenjin – seems to be only for the server side
- Ajax Pages – ERB-like syntax
- John Resig’s micro templating – ERB-like syntax
- Template class from Prototype
4 comments:
Justin Meyer
EJS files should be in a separate file (not embedded in HTML). Dude, have you checked out JMVC? It's built for exactly what you are doing. JMVC includes a much more powerful and faster version of EJS.
Seriously, I'll help you switch. My email is justinbmeyer AT (Google's Email Application) DOT COM
Jeff Rose
It looks like you've found the same templating engines I did during my search, as well as a couple more. In general I'm not happy with any of them. I want the template to be valid (X)HTML, which leaves PURE, noTemplate, or Chain.js. Unfortunately I've encountered uses cases that none of them do. My hope is that PURE2, which is currently under development, will be more robust.
I wouldn't mind seeing a JavaScript templating engine go the Wicket route with its syntax, that is using an XML namespaces.
Kernel James
There's also Distal templates http://code.google.com/p/distal which allows the HTML to remain valid HTML.
Hindi
Any additional libraries anyone can suggest in 2017.