Underscore Templates
It has come to my attention that perhaps Underscore templates are a bit misunderstood. Or, perhaps, the community is simply unaware of their best features and usage. Either way, I’d like to provide a primer for the uninitiated and a knowledge base for the rest. The goals and benefits of client side templating have been explored fairly thoroughly so I’ll jump right into the good stuff.
There are lots of code examples below, so make sure to play around with anything you don’t understand. Just head over to underscorejs.org and open up the console.
Basics
Based loosely on John Resig’s micro-templating, Underscore
templates should have a fairly familiar feel. Put in some text with delimeters
for your data, and _.template
does the substitution for you, easy peasy.
The syntax is flexible so don’t rage quit if you dislike <%= %>
. You can
just use different delimiters. Need to HTML escape your data? No problem,
just use <%- %>
.
Underscore templates also happen to be logical (as opposed to logic-less), allowing you to use whatever crazy javascript you can come up with. I happen to enjoy this sort of freedom but if it’s not your cup of tea, don’t sweat it.
Custom Delimeters
If you’d prefer a different set of delimeters, you can easily provide your own regular expressions for interpolating, escaping, and evaluating. Each regular expression must provide exactly one capturing group.
These options can also be set globally via _.templateSettings
.
Compilation
If you leave out the data argument, you are returned a plain old function that you can execute many times over without the overhead of compilation.
You can inspect the template source via the source
property, which is handy
for precompiling your templates. It’s crazy fast compared to compiling on each
load and, more importantly, it provides useful line/column numbers in stack
traces.
While it might seem a bit esoteric, viewing the template source is rather instructive. First and foremost, it proves that templates are just javascript, no magic involved. Secondly, it provides for some interesting techniques.
Slow by Default
Since version 1.3.3, underscore templates have been quite fast.
However, backward compatibility concerns force them to be slow by default. By
specifying a variable
to prefix your data with, you can speed things up by an
order of magnitude.
When a variable
is not specified, the template source is wrapped in a with
statement. While there are plenty of existing
implications regarding the with
statement, we’re
only concerned with performance here and the with
statement makes things
much slower.
Template Context
While, in my experience, under-used, a template is always provided with a
context, which can be quite useful when rendering your views. This prevents
the need to pass a custom data argument to your template, sparing you from
memorizing yet another application custom API, not to mention creating another
custom API at all. This is maybe my favorite _.template
technique but
has gone unnoticed by most.
I find it particularly useful in Backbone views but it’s equally useful when rolling your own.
Further Reading
This post actually turned out relatively small, which I think is a testament to
the simplicity of _.template
. If you want to dig deeper I’d suggest reading
the source, as there really is no substitute. :)