Using Partials to Ease Website Deployment  May 17th, 2008

My first few posts were about adding a bit of dynamic behavior to a web page. This is all very 'flashy' and 'cool', but often it's not the end result I need help making dynamic but the 'build process'. So many times I've had to make a tiny change to a part of a site (say, the footer) and in no time I've buried myself in copy-paste-hell trying to fix all occurrences in the whole site. Sure, sure, sed, grep, etc are quite literally created for this sort of thing, but... well, I just really want a lo-fi solution that a regular user (say, a client) could use.

The Example

I want to have an html page where instead of:

I can write something more like:

So we'll need a 'build phase' which will go through our source files and replace things like <%= partial 'something.html' %> with the actual content from, something.html.partial.

This will be very, very handy. What if it's 2009 now? I have to go through every single page in the entire site and update the number. I'll miss one, forget one, screw up one by removing a > somewhere or a semi-colon from an XHTML entity. Bah.

By doing something like this we can keep one copy of content like the site footer in footer.html.partial, and just stick it on every page that asks for it during the build phase. Even better, we can pull in these partial pages from essentially anywhere. Put them somewhere on the webserver itself and we can grab them with CGIs too so that even dynamic pages will have the most up to date content.

But that's enough talk, let's get to it.

The Requirements

What tools should we use for this? It isn't a performance critical process. Rake is awesome. Ruby's syntax is super sexy. I'll write this tool in Ruby. So:

On OSX you most likely already have everything you need. On GNU/Linux you can most likely just use the package manager for your distro (eg. sudo aptitude install ...). On Windows, I suppose you'll most likely want the 'One-Click Installer'.

The 'Builder'

This really isn't too complex. We write a rake task in a file called Rakefile so that we can go into the root of our website and type rake which will construct our website out of the source files we've written:

First we define two functions. One to output the result of all our substitutions to the right place. Another, the partial function, is what we're actually calling in our pages when we say <%= partial 'something.html' %>, it just opens up the file by name, adding .partial and returns the text it contains. Of course, it will only do that if the partial exists, otherwise we show an error.

Now the easy part. The rake task itself is just taking a FileList (the files we want to 'compile'), excluding files that end in .partial (since, well, we'll use them later -- they aren't pages by themselves), and then just letting ERB perform it's magic on the contents. When ERB hits a call to partial in a file, we just insert the result in place.

When we run rake (or rake build, you could define any number of different tasks) we will see output explaining what's going on. For example, this blog post's output looks somewhat like so:

That's really all there is to it. A tool like this is quick and easy to write, easily extensible and, if you ask me, fun to write... But there's lots of other ways to accomplish similar things. You could use anything from full web application frameworks like Rails or Django, a server-side pre-processing language like PHP, or even a system like Webby, the list goes on and on. Why not use one of these?

Well, other than a blog being one of the only appropriate places for NIH syndrome, I have my reasons. Most of the time I don't want to do per-request processing (this rules out any sort of 'framework' -- Rails, PHP, etc). Webby, though, is great. I have no real excuse not to use it. But in my experiments it still seemed like overkill, too general for my typical use case.

The Code

The best kind of code is free code. So the full source including some enhancements (like syntax coloring and a simple task for deploying over SSH) is available under the MIT license.

Some social stuff: