Clojure HTML Templates
In this guide, I describe the available HTML templating options for Clojure and give my recommendations.
Recommendation summary
Choose Hiccup if you would like to embed HTML in your code. Hiccup uses an easy-to-write, literal data format to represent HTML.
Choose Selmer if you would like to embed code in your HTML. Selmer embeds code-like directives inside of text strings. It also works directly from files.
Introduction
When you are serving up HTML pages from the backend, you will need a way to easily generate HTML. You need to generate HTML dynamically based on the data that you wish to display. You will need to loop through lists of data and display different things conditionally. Loops and conditionals? That's code. There are really two choices:
- Embed code in your HTML
- Embed HTML in your code
Both of these approaches have their benefits. You can find good arguments on both sides. Let's summarize them here.
Why would you embed code in your HTML?
The main argument to embed code in your HTML is that your HTML files still mostly look like HTML. That means anyone who is familiar with HTML can modify them. That group might include your designers, for example. The language for the code embedded in your HTML is usually very basic and easy to understand. It is done so on purpose, so that your templates don't start to have domain logic in them. Instead, they should have what is known as display logic only. Display logic says stuff like "if the button is active, make it red". Display logic only deals with how the HTML gets generated.
Why would you embed HTML in your code?
The main argument to embed HTML in your code is that you have the whole power of your main language to work with. Besides simple loops and conditionals, you may want other ways of manipulating your HTML. In Clojure, many of the HTML libraries that embed HTML in your code do so with data representations of the HTML. For instance, Hiccup uses vectors to represent HTML tags. That means you can easily concat things together.
You're going to have to decide which of these two you prefer. If you can't choose, default to embedding HTML in your code.
Highly recommended
These are my picks for HTML generation in Clojure projects.
Embedding HTML in your Clojure code
Hiccup is the most common way people generate HTML from their Clojure code. Hiccup is a very readable format based on Clojure literal data structures. If you can read Clojure, you can read Hiccup. It looks like this:
[:div#main-content.blue-background.green-border
(h "Here's some content")]
That creates a div with an id, two classes, and some text content.
Hiccup has a number of great features.
Use the whole Clojure language
Because Hiccup is just Clojure data literals, you can nest Clojure and Hiccup together seamlessly. Use conditionals, function calls, and any other way of generating data to make Hiccup. There's no need to learn another language. You can use your REPL-Driven Development skills to check the output. Most of the time, though, you can see the structure as a literal data structure.
Use functions to abstract
You can return Hiccup from functions. That gives you a means of capturing and naming repeated functionality. No need for a fancy import system.
Get the HTML right
HTML has some tricking syntax. Did you know it's illegal to self-terminate a <script> tag? Hiccup has all of those rules built-in, so you don't have to worry about them. Hiccup's syntax is more regular than HTML.
Compilation for fast generation
At some point, Hiccup's vector data structures need to get turned into a String or OutputStream to be sent to the browser. Luckily, a lot of that work can be done at compile-time because the structure of the HTML is often known at compile-time. Hiccup uses a macro to compile its data representation to fast code (essentially a bunch of String concatenations) so that the data structure doesn't even need to be realized at runtime.
Id and class shortcut
Hiccup has a nice way of writing HTML id and classes that is reminiscent of CSS id and class selectors. This is often more readable than the regular HTML version.
Generate Hiccup from HTML
If you've got some existing HTML, you can turn it into Hiccup representation with a choice of tools.
But Hiccup has a major downside you should be aware of.
Beware: security is lax by default
Hiccup makes the wrong choice for handling Strings. It forces you, the
programmer, to explicitly escape dangerous Strings. If you forget to
escape user-generated content, you leave your site open to cross-site
scripting
attacks.
The better way would be to escape all strings by default and force you
to be explicit in the rare case where you do want to allow a String
unescaped. If you want this more secure functionality, you should use
the
hiccup2.core
namespace.
Otherwise, Hiccup is rock solid and many large companies use it.
Embedding code in your HTML
Selmer is an excellent, well-supported option for embedding display-logic directives in your HTML (or any other text format). Selmer is inspired by Django templating. It is used as part of the Luminus framework. It has a number of nice features. Selmer templates look like this:
<ul>
{% for item in items %}
<li>{{item}}</li>
{% endfor %}
</ul>
Work from Strings or files
Selmer is flexible. It will work from strings of template text or from files that contain the template text. When working with files, it will cache them.
Compiled templates
Selmer compiles templates to generate fast code for rendering to strings.
Rich set of filters and tags
A lot of display-logic stuff, like capitalization, is built into the language, in the form of filters. Tags let you do conditionals and loops.
This is an excellent choice for using HTML files to generate server output.
Other options
Over the years, there have been a number of other attempts and experiments at generating HTML from Clojure. I won't list them all, since there are so many.
Embedding HTML in your Clojure code
Enlive is a commonly-cited HTML templating engine for Clojure. It parses in HTML and stores the templates internally as nested maps. Since it's data, there are many powerful operations that can be done with it. It was also created very early, and so many people used it in the early days. However, I don't recommend using it unless you absolutely need one of the features. In my experience, the features that make it unique (such as query selectors) are too slow to use in production. (If you need fast query selectors, go with jsoup.) The typical web application only needs a few important features, such as writing HTML, abstracting it with functions, and embedding logic. Beyond that, any other features are overkill and not worth sacrificing speed for.
Embedding code in your HTML
Mustache is another common web templating language that is defined to be very limited in terms of the kinds of logic. There's a reason: the less logic you can put in your template, the less likely you are to start adding domain logic instead of display logic. If you want mustache templates, check out Stencil.