The Quest for the One True Static Site Generator
October 10, 2015When I started blogging back in 2005 I created my personal blog on Blogger. I’ve been using this excellent blogging service over the years, enjoying the luxuries of not having to deal with the intricacies and complexities of hosting providers and blogging engines. Somewhere last year I started to get interested by the rise of static site generators. These days every self-respecting programming language has one or more associated static site generator tools.
What particularly piques my interest in static site generators is their promise of simplicity. Just spitting out some static HTML, CSS and JavaScript files. Fast to serve by any web server. Back to basics.
So at some point I started my quest to move away from Blogger. The tool I used for the job was Octopress, built on top of the ever popular Jekyll. This meant that I could host my personal blog on GitHub. What’s not to like?
Everything migrated smoothly and I got things set up in no time. But somehow I lost my excitement when everything went online. During the migration I constantly had to Google questions and answers, never having the feeling that I knew what I was doing. As soon as I started working on a new blog post, I got frustrated by the impediments it posed on my writing flow. Having a backlog of 10 years of blog posts ultimately seemed to have a negative impact on the performance of the output generation process. Who knew?
So after almost a year of not blogging, I decided to migrate again to another static site generator. This time I went for raw performance by adopting DocPad. At least, that’s what I thought at the time.
I spent a lot of time in order to get things working. I chose Jade as my templating engine, but got really frustrated by the terseness of its syntax, constantly struggling with the significant whitespace issues. I’ve used Jade in a couple of other projects in the past but I did not remember that it caused me so much pain.
Furthermore, some DocPad plugins were generating errors and/or warnings because they were out-of-date or using some part of the internal DocPad API that had been rendered obsolete in a more recent version, etc. … I constantly had to make compromises regarding the blog features that I wanted to implement because I didn’t get things to work just the way I wanted. After a frustrating couple of weeks I got something going. I pushed it to a brand new server at DigitalOcean and lost interest again.
When I decided to write another blog post, I noticed how very slow the generation process went. Again the impediments and negative impact on my writing flow. Not cool.
A couple of months ago I ran into yet another static site generator named Nanoc via One Thing Well. This one has been around for several years now. I started reading the documentation and instantly got a prototype working. Before migrating my personal blog again, I decided to use it for another static website that I created for my son’s soccer team in order to discover its features and applicability.
I totally loved how simple and easy it was to get things set up. For this website I had a couple of specific issues that I wanted to solve, like quickly adding photo albums and news items. I was able to implement a new version of the website in no time, growing ever more enthusiastic about Nanoc. After this successful venture, I decided to migrate my blog yet again, this time to Nanoc.
Having created two static websites with Nanoc, I couldn’t be happier about how everything turned out. One of the things I like the most is that I can just use plain old HTML interspersed with some erb. Layouts, partials and captures are all at your disposal.
Compilation and routing rules contained by the rules file are pretty amazing and easy to set up. Suppose I want to set up custom routing for all articles on my blog, using the year, month an the slug. Here’s the code to accomplish this:
route '/articles/*' do
year, month, day, slug = /([0-9]+)\-([0-9]+)\-([0-9]+)\-([^\/.]+)/
.match(item.identifier).captures
"/#{year}/#{month}/#{slug}/index.html"
end
Processing markdown files and/or HTML files is as easy as adding the following compilation rule:
compile '/articles/*.{html,md}' do
filter :erb
filter :kramdown, :enable_coderay => false, :input => 'GFM', :hard_wrap => false
layout '/article.*'
end
Here we first process the erb code, then process the markdown syntax using the GitHub dialect and render the output using the article layout. This is all I had to do in order to correctly process all legacy blog posts (HTML) as well as the newer ones (markdown).
Oh, and rendering the entire blog including 10 years of blog posts takes about 30 to 40 seconds on my machine, which is pretty awesome compared to Jekyll and especially Docpad.
Generating output pages from virtual items added from code is a pretty advanced scenario, but almost as easy to set up as the basic stuff. An example of this is generating a page for every unique tag used by a blog article.
def create_tag_pages
get_list_of_tags.each do |tag|
sanitizedTagName = sanitize_tag_name(tag)
@items.create(
"= render('_tag_page', :tag => '#{tag}')",
{ :title => "#{tag}", :tag => "#{tag}", :is_hidden => true },
"/tags/#{sanitizedTagName}/",
:binary => false
)
end
end
If you’re in need for a decent static site generator, then look no further. Using Nanoc is an easy and above all, a very fun way to generate static HTML content.
Until next time.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be