Deploying Jekyll to Heroku
So you have a static site in Jekyll that you want to deploy to Heroku. Lucky for you, this is a relatively easy task and does not require anything as complex as a deployment server as mentioned in the Jekyll docs. You can support this with a simple Rack script.
For those not familiar, Rack is a bare-bones web-server adapter in Ruby. Most Ruby web-frameworks sit on “top” of Rack while the Ruby web-servers sit “underneath” of it. However, we don’t need all the complexities of a web-framework to serve our static content, so we only need Rack and any Rack-compatible web-server to accomplish our goals.
Requirements
The bare minimum that you’ll need are
- Jekyll site to publish
- Your favoriate text editor
- Heroku account to push to
- Ruby (recent version)
- Bundler (gem)
There are a lot of ways to install Ruby so I’ll leave this to you. I will say that I prefer rbenv for its ease of use. Once you have Ruby set up, you can install Bundler via
Gemfile
The first thing we need to declare is all of our runtime requirements for our Rack
script that we’ll write later. Put this in a file called Gemfile
This file is rather simple, we’re stating the source of our gems (the official repo),
the Ruby version (2.2.0
) and a couple of gems. The rack-contrib
gem will pull in
some stuff for static-asset serving (as well as rack
itself) and puma
is
our Rack-compatible web-server.
Once we have our Gemfile
we need to create a lock
file. This will be used
to “lock in” specific versions of gems so that what we try out locally should be
exactly the same when we deploy it to Heroku. We can create this with
You should now have a Gemfile.lock
in your directory. Do not edit this file.
Rack
Now that we have the required gems installed, we can get down to writing our Rack
file that will serve our static assets. Create a file config.ru
with the
content
Let’s break this file into the important parts. The first thing we do is import the required gems. This is self explanatory. Next we see
This bit of code will enable compression on any content that is served. This will speed up your page load time, especially for those with slower internet connections. The next section is the real meat of our Rack file
This portion defines our static asset handler. The first thing it does is set the “root” of the
content directory to _site
. This means that if a request comes to /index.html
that our static
asset handler will look in _site/index.html
. Since _site
is the default folder for Jekyll
auto-generated content, we should be good to go here.
The url
defines how we want to match requests. If we wanted to have a Jekyll site as only a
sub-section of our site, this would be useful. Since, for the purposes of this example, the Jekyll
site comprises the entire web-site we can define this as /
to mean the “root” of the web-site.
The try
defines various extensions to try when receiving a request. So given what we’ve seen so
far, if the application receives a request of /awesome-article
it will check for the following
files in order
_site/awesome-article
_site/awesome-article.html
_site/awesome-articleindex.html
_site/awesome-article/index.html
With this we can make a variety of requests and get very clean URLs without having to include the
.html
extensions or without having to specify index
when visiting the root of the site (e.g.
www.mysite.com
).
The gzip
and header_rules
options simply allow caching to work which we defined earlier. This
should help to significantly speed up your site, especially as visitors click from page to page as
they will avoid re-loading common resources such as CSS or JS files.
This last part is especially nifty.
This will redirect any request that we can’t understand (broken link or just bad URL) back to the homepage. You could, if you wanted to be really fancy here, provide a custom “Not Found” page. Let your imagination run wild.
Procfile
If we are deploying to Heroku, we need to create a Procfile
that tells Heroku how to run our site.
We can create a simple file as
This instructs Heroku to use our puma
gem to run our web-service and some additional parameters that
Heroku requires (you can safely ignore these).
Releasing!
We are now ready to push to Heroku! Assuming you’ve already setup your Heroku account and have authenticated in your local repo. We can run the following bit to deploy.
Personally, I like to put all of this into a Makefile sot that I can automate this process.