I’m going to try to outline your current choices when generating HTML in Clojure. To enable you to skip the entire article: there are no bad libraries, but they’re very different and suitable for different things. If you need to, there’s nothing stopping you using multiple technologies in different parts of the program.
I’d be lying if I said I was an expert on any of these technologies, so please feel free to correct me.
If there’s a default stack for Clojure, it’s the work done by James Reeves. Hiccup is an HTML DSL for Clojure, like HAML but everything is valid Clojure. The principal advantage of doing thing is this way is the ability to build things on top of it: if you want to create an API for standardized HTML components e.g. a form library, Hiccup’s your friend.
With Hiccup, you’re going to be ready to roll in about ten seconds after you’ve read the documentation, and it’s extremely fast. (I’ll let someone else run the micro-benchmarks.) However, it’s a bit fiddly, precisely because it’s very low level and macro-friendly.
If James Reeves is the Beatles, Christophe Grande is the Rolling Stones of Clojure Web Development.* Enlive is the most insanely fully featured project here. For instance, the latest version contains a helper with the entire functionality of Hiccup.
Enlive is properly an HTML parsing and transformation engine based on JSoup, but it contains a capable templating solution. Here you provide external files that are valid HTML with no additional markup It then performs transformations on nodes you identify using a CSS-like syntax. The transformation you’re going to be using most often, of course, is to insert some text or HTML, but you can do arbitrarily smart things here.
Enlive does have an acknowledged weakness: the documentation. There’s some good introductions, but Enlive is ridiculously deep. However, if you the time in, you’ll find it’s incredibly powerful and elegant.
Laser is a new project by the talented Anthony Grimes. It aims to take the best parts of enlive and put them into a simpler package. The syntax is more verbose, but fully composable (everything’s a function).
It also has the ability to use unparsed HTML in its output, which Enlive discourages.
Neither Hiccup nor Enlive are very close to a traditional templating engine as you’d expect to find in other languages. It seems like node has as many templating solutions as it has developers. Clojure, at the time of writing, basically has two.
Fleet is a classic “mix code with your markup” templating language. You can insert arbitrary functions into your HTML, like class ASP and ERB. It also has a host of support functions, including the ability to create namespaces on the basis of a directory of templates.
Clostache, on the other hand, is a mustache implementation. It is programmable, but only in limited and well-defined manners. Whilst Fleet has an extensive API, Clostache declares only two methods: render and render-resource.
Choosing an Engine
When choosing between node libraries, the principal question was “does it work?”. And the answer was, typically, “not after you’ve been using it for half an hour”. Clojure libraries just aren’t like that. All of them are good at what they do.
The biggest question here is: what’s your approach to templating? If you believe in pure HTML templates, Enlive or Laser is for you. If you want lots of code in your HTML, you’re going to want Hiccup or Fleet. If you’re looking for somewhere in between, Clostache is worth a look. And, as I said before, you can always use one solution for one part of your system and another elsewhere. That said, the different systems aren’t composable with one another, so be very clear as to what you’re using each for. (I’m pretty sure this is why Enlive has added hiccup-style generation.)
For what it’s worth, my current project uses Clostache for straight forward page serving and Enlive for HTML reprocessing, although I’m thinking about Laser. To date, I’ve found it pretty easy to change my mind about which libraries to use. I’ve never found that with any other platform. I’m ascribing that to the design of Clojure and the aesthetic of the community, and it’s a huge win.
(NB For some reason my blog won’t take comments from Chrome. I promise I’m working on it, but it’s taking a while. A long while.)