We’ve recently really taken a liking to building and deploying static sites using middleman. Middleman is a ruby gem that uses a tool chain familiar to rails developers, and simple enough to grasp for those less familiar with rails, and even ruby.
Before we dig into middleman, here’s a little wishlist of an ideal static site development tool:
- Dynamic code reloading in development via livereload or browsersync.
- Blogging built-in.
- Easily utilize latest development tools such as SCSS / Compass, Less, Coffeescript, etc.
- Templating language / layouts to reduce code duplication.
- Entire site can be compiled to static html in a single command.
- Rails-style approach to production assets. This means we need to be able to use a CDN to serve hashed assets. The ability to use hashed asset URLs is important in production so we can set far in the future cache headers and serve those assets through a CDN like Cloudfront, Akamai, Cloudflare, et al.
- Can be deployed on a normal web server without a backend. Preferably on Amazon S3 or something similar with Cloudfront serving assets.
Middleman to the Rescue
Middleman enables a very familiar and productive workflow: a rich toolchain during development, but with the ability to compile the site down to static HTML and deploy to a simple webserver like Amazon S3.
Development with Browsersync
Middleman comes with built-in support for livereload, but I prefer browsersync (Node.js), as it’s a bit more responsive to file changes due to it’s architecture. Using it with middleman is painless:
1 2 3
npm install -g browser-sync middleman server browser-sync start --proxy 'localhost:4567' --files source
middleman server launches a ruby dev server on port
has a handy
--proxy mode that sits in front of another server and proxies requests
to it. When browsersync starts up, it’ll look for the first available port starting
with 3000 and it’ll open a new chrome tab on
localhost:3000 instead of 4567.
Now, any changes you make will trigger an automatic page reload.
To make things a little easier, we like to stick these two commands in a Procfile and run our development environment using foreman.
browsersync: browser-sync start --proxy 'localhost:4567' --files source server: middleman server
Middleman comes with a built-in blogging extension.
Add it to your Gemfile:
Activate it in the middleman
Generate a new post with the middleman helper:
middleman article "Article Title"
Read more about the middleman blogging extension here.
Compiling to Static HTML
Middleman comes with a handy
middleman build command which takes your existing
site and compiles everything to static HTML. The build command writes your entire
site to the
build directory, making it easy to ship to a deployment server.
Deployment to Amazon S3 and Cloudfront
Deploying the site to S3 is super simple thanks to the middleman-s3_sync extension. Add it to your Gemfile, and configure it in your config.rb file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
activate :s3_sync do |s3_sync| s3_sync.bucket = 'yourdomain.com' # The name of the S3 bucket you are targetting. This is globally unique. s3_sync.region = 'us-east-1' # The AWS region for your bucket. s3_sync.aws_access_key_id = 'ACCESS_KEY' s3_sync.aws_secret_access_key = 'SECRET_ACCESS_KEY' s3_sync.delete = false # We delete stray files by default. s3_sync.after_build = true # We do not chain after the build step by default. s3_sync.prefer_gzip = true s3_sync.path_style = true s3_sync.reduced_redundancy_storage = false s3_sync.acl = 'public-read' s3_sync.encryption = false s3_sync.prefix = '' s3_sync.version_bucket = false end
The S3 sync extension also supports loading your credentials from a
located in the project root directory. You should use this to keep your Amazon
credentials out of source control.
There are two ways to ship your build directory to S3. You can enable the
setting in your s3sync config, which will automatically deploy your site to your
S3 bucket after running
middleman build, or, you can run `middleman s3sync` manually.
Check out this page from AWS for more info on hosting a static site on S3.