Project

rackstatic

0.0
No commit activity in last 3 years
No release in over 3 years
Stop treating static-site generators differently than web frameworks. Build your static site using any rack-compatible web framework, then generate a static version with the rackstatic(1) command.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 0.5.6
>= 1.5.2
>= 0.6.2
 Project Readme

Introduction

There's this category of web framework called "static-site generators", or "SSGs" for short. We, as developers, use them because it's easier than the alternative: writing a regular server, then launching it, mirroring the contents using some arcane wget incantation, and shutting it back down afterward.

But while SSGs eliminate this particular hassle, they come with their own: they require you to organize everything their own persnickety way; they don't follow common web-development practices; you have to write special plugins for them if you want to use any templating library or database adapter or whatever else that would "just work" anywhere else. It's almost less work to use wget.

rackstatic cuts this Gordian knot. Using rackstatic, you can develop your static website in, say, Sinatra, or any other Rack-compatible web framework (yes, even Rails, if you really really want.) And it's just as easy as using an SSG.

Here's the deal:

$ gem install rackstatic
$ cd your_rack_app/
$ rackstatic dist/

A static mirror-copy of your website will now exist under your_rack_app/dist/.

If your repo is laid out such that your application files (config.ru et al) exist under your_repo/app/, you can build from above it to keep things clean and separate:

$ gem install rackstatic
$ cd your_repo/
$ rackstatic dist/

This will use the app in your_repo/app/ to build your_repo/dist/.

How does it work?

rackstatic uses the mock Rack session functionality of rack-test. Except, not so much for testing 😀. Instead, the response bodies returned in each mock request are written to disk, then spidered (using nokogiri for parsing) to find more URLs to request.

What about static files?

Some files aren't linked anywhere: robots.txt, crossdomain.xml, favicon.ico, and so forth. A regular spidering-based mirroring process would miss these.

To prevent this, rackstatic will attempt to request anything it sees under your_rack_app/public/ (e.g. your_rack_app/public/robots.txt ⇒ GET /robots.txt), as if they had been linked to. You can change what subdirectory of your app is looked under using the -s switch:

$ rackstatic -s static/ dist/

Recommendedations

You should add rackstatic to your Gemfile. Then, when you pull down your app from its repo, building it is as simple as:

$ bundle install
$ bundle exec rackstatic dist/

You can also add a deploy task to your Rakefile that calls rackstatic. Rather than messing with shell commands, try the Rack::StaticBuilder API:

task :deploy => [:build]

task :build do
  require 'rack/static-builder'
  begin
    Rack::StaticBuilder.new(:app_dir => 'app/', :dest_dir => 'dist/').build!
  rescue Rack::StaticBuilder::BuildError
    fail "one or more resources returned a non-2XX status"
  end
end