Simple media cachebusting with GitHub pages

GitHub Pages makes it really easy to host static websites, including sites with custom domains or even with HTTPS via CloudFlare.

However, one typical annoyance with static site hosting in general is the lack of cachebusting so updating an image or stylesheet does not result in any change in your users' browsers until they perform an explicit refresh.

One easy way to add cachebusting to your Pages-based site is to use GitHub's support for Jekyll-based sites. To start, first we add some scaffolding to use Jekyll:

$ cd "$(git rev-parse --show-toplevel)
$ touch _config.yml
$ mkdir _layouts
$ echo '{{ content }}' > _layouts/default.html
$ echo /_site/ >> .gitignore

Then in each of our HTML files, we prepend the following header:

---
layout: default
---

This can be performed on your index.html file using sed:

$ sed -i '1s;^;---\nlayout: default\n---\n;' index.html

Alternatively, you can run this against all of your HTML files in one go with:

$ find -not -path './[._]*' -type f -name '*.html' -print0 | \
    xargs -0r sed -i '1s;^;---\nlayout: default\n---\n;'

Due to these new headers, we can obviously no longer simply view our site by pointing our web browser directly at the local files. Thus, we now test our site by running:

$ jekyll serve --watch

... and navigate to http://127.0.0.1:3000/.


Finally, we need to append the cachebusting strings itself. For example, if we had the following HTML to include a CSS stylesheet:

<link href="/css/style.css" rel="stylesheet">

... we should replace it with:

<link href="/css/style.css?{{ site.github.build_revision }}" rel="stylesheet">

This adds the current "build" timestamp to the file, resulting in the following HTML once deployed:

<link href="/css/style.css?da39a3ee5e6b4b0d3255bfef95601890afd80709" rel="stylesheet">

Don't forget to to apply it all your other static media, including images and Javascript:

<img src="image.jpg?{{ site.github.build_revision }}">
<script src="/js/scripts.js?{{ site.github.build_revision }}')">

To ensure that transitively-linked images are cachebusted, instead of referencing them in the CSS you can specify them directly in the HTML instead:

<header style="background-image: url(/img/bg.jpg?{{ site.github.build_revision }})">

Comments (2)

Anonymous

Alternatively, couldn't you just use CSS and JavaScript filenames that include hashes of the content? Many site generators can do that.

Dec. 9, 2017, 5:55 p.m. #
Sure. But can you do it on GitHub...?
Anonymous

Sure, just push the results of the site generator.

Dec. 10, 2017, 5:18 p.m. #
Well of course, but then you are adding another hurdle for people to contribute. :)