Middleman + Enlive: The best thing since PHP
Before I begin, the ideas in this article were introduced to me by this blog post, which I consider a must-read for anyone who uses Clojure on the web.
I've been using Clojure for web development a lot more lately. This can be a contentious topic for some people. “Clojure is hard to hire for”, they say. “It's for pretentious nerds”. “It's overkill for the web”.
I've been struggling with the fact that I can't really defend against any of the above, but that I love making apps in Clojure anyhow. Sure, there's nothing as cohesive as Django or Rails that exists for the Clojure ecosystem (Noir was a good effort but is no longer maintained, and didn't have a data layer anyhow). However, Ring makes it incredibly easy to make your own powerful abstractions. Compojure provides a comprehensive routing framework that takes a lot of the effort away. It's up to you to choose your data provider, but you can plan on passing around maps of data effortlessly. But it's the generation of HTML that I want to talk about today.
Every since PHP hit the scene, the story of going between code and HTML has been through templating. PHP brings its own. ASP copied PHP. Ruby these days uses Liquid or ERB or Haml (arguably more than a templating language, admittedly). Django uses its own templates, which look a lot like Jinja2 (or vice-versa). Mustache implementations exist for an incredible array of languages (including Clojure!), and I've been using Mustache a lot lately because it really makes a good – but incomplete – attempt to remove logic from templates.
None of these, I've discovered, have a damn thing on Enlive.
Enlive changes the definition of “template”
Enlive is library for working with HTML. It seems to have its roots as a tool for scraping, but these days, people use it instead of a templating language to produce HTML from data. The gist is that you pass Enlive a fully-formed HTML document, and it parses it into a template. Then, you feed it rules transforming the template as you need. You can change attributes, text, add or remove elements, copy/replace elements, and basically mutate the HTML any which-way. The “template” lives in your code, not your HTML.
Why is this so powerful? This means that you don't need to write special HTML-with-code-in-it; you can take an HTML mockup and plonk it directly into your project as a template resource, and let enlive take out your placeholders and put in real data. This in turn opens the door for you to use a static site generator like Middleman, which turns out to have numerous benefits.
Middleman to the rescue
Middleman is a way to make static sites. In other words, you feed it HAML or ERB, and it produces HTML. Ironic, I know, but we're not using HAML or ERB for logic, we're using them to save time.
Middleman works a lot like Rails templating; you define a layout file with a yield keyword somewhere in it, and then you put all the common stuff in the layout and all the page-specific stuff in the page.
The result is a static HTML site. In your case, it's HTML mockups of every UI page in your application – mockups that will actually be used in your site to generate those UIs!
What's so great about this workflow?
(Really) separate presentation and logic
This is the closest anyone's come to complete separation of presentation and logic, as far as I can tell. You could have someone who doesn't have any idea how your program works write all your HTML for you, and then you can come in and make a UI out of it.
Separation of thought
It's freeing not having to think about logic when making your UI. You won't get this until you try it, but the ability to context-switch between designer mode and developer mode without having to be both at once is a much more comfortable arrangement.
Fast UI iteration
As long as the HTML structure is similar enough, you can totally change your UI and your code will still work. No thinking about looping over this or that template variable and what HTML that generates and how it fits in and if all your tags are closed. Just write your HTML and copy it over.
Generate HTML however you like
Middleman is a great tool, but you don't have to use it. There are a ton of static site generators out there. I just like it because I enjoy writing HAML more than HTML.
Ok. Here's a toy app I wrote a little while back: http://wagr.herokuapp.com/
And here's the ENTIRE view code:
If you use Clojure, or want to use Clojure, to make websites, I strongly encourage you to check out Enlive.
So why Clojure?
Clojure, being a proper lisp, makes it really easy to create DSLs like Enlive. “Shape your language to your problem” and all that. But there's no reason why this sort of thing couldn't exist in Ruby or Python or Java or even PHP or anything else. But I like Clojure just fine, so it's not going to be me that builds it. If you've seen it, though, let me know.
If you'd like to discuss the broad assertions I've made here, the best place is probably the Hacker News submission
- Apr 7, 2013: Clojure web apps: Zero to 'Hello World' on Heroku in Clojure in 15 minutes.
- Jun 24, 2013: Learn Clojure in 15 minutes, perhaps