This little website’s currently powered by some software called Jekyll. I’m generally into it, as these things go, and thought I’d write up a couple things I use on my website. Nothing remotely groundbreaking follows, mind — just two tricks that’ve made working with Jekyll a little easier for me.


№ 1: Cache busting with _config.yml

If you look at the code for this entry, you might see something like this near the top of the document:

<script src="/dist/js/initial.20180218.js"></script>
<link href="/dist/css/main.20180218.css" rel="stylesheet" />

A link to a JavaScript file, and a link to my stylesheet. (You’re shocked, I can tell.) Thing is, those files with the unwieldy-looking names? They don’t actually exist anywhere on my server. initial.js and main.css do, but initial.20180212.js and main.20180212.css are fictions.

This is a little trick I’ve borrowed from Jeremy Keith, burying version numbers in filenames for some cheap cache-busting. Using Jeremy’s approach, and a little technical jiggery-pokery, my server sees this markup:

<script src="/dist/js/initial.20180218.js"></script>
<link href="/dist/css/main.20180218.css" rel="stylesheet" />

and translates it into this:

<script src="/dist/js/initial.js?version=20180218"></script>
<link href="/dist/css/main.css?version=20180218" rel="stylesheet" />

A little file versioning, a little cache-busting — and all without unsightly query strings.

Now, I could hand-code those values into my template, and update the markup each time I push a new fix for some horrid, world-breaking CSS I wrote update my design. Instead, Jekyll has a system file called _config.yml, where various options are set for your website. You can define various stock settings, as the documentation’ll tell you. However, you can also define arbitrary values you might need to reference in Jekyll templates. For example: if there’s a cats variable in _config.yml, your templates can reference it as site.cats.

Sadly, there aren’t any cats in my config. What I do have, right at the top, is this:

# Version number
build: 20180218

You might’ve guessed it: that build variable also appears at the top of my default template.

<script src="/dist/js/initial.{{site.build}}.js"></script>
<link href="/dist/css/main.{{site.build}}.css" rel="stylesheet" />

And when my site’s generated, that’s transformed into what you see in the code powering this post.

<script src="/dist/js/initial.20180218.js"></script>
<link href="/dist/css/main.20180218.css" rel="stylesheet" />

Whenever I push a new version of my site, I simply update the build variable in my _config.yml, and the new version number’s immediately baked into every page of my website.

№ 2: Everything’s liquid, baby

I recently learned that if you’ve got front matter in any file — CSS, JavaScript, what have you — then Jekyll will open it up, and process what it finds. For example, the very first lines in my htaccess file are:

---
layout: null
---

These three lines signal to Jekyll that it shouldn’t just move this file to my _site directory. Instead, it should review the contents of the file, and evaluate any variables or commands it might find.

This is wildly handy when, say, you’ve donked up various important files with weird-looking version numbers, and you’d like to make sure to include them with HTTP/2 server push:

<FilesMatch "\.html$">
  H2PushResource add /dist/js/initial.{{site.build}}.js critical
  H2PushResource add /dist/css/main.{{site.build}}.css
</FilesMatch>

When my site’s built, Jekyll looks at the value of build in my _config.yml — just as it did for our cache-busting markup up above — and translates it into this:

<FilesMatch "\.html$">
  H2PushResource add /dist/js/initial.20180218.js critical
  H2PushResource add /dist/css/main.20180218.css
</FilesMatch>

This also works beautifully in my service worker, which makes this site offline-friendly. The very top of the file looks like this:

---
layout: null
---
( function() {
  "use strict";

  const version = "v{{site.build}}";
  const cacheName = version + "::ethanmarcotte:";

  …
} );

Thanks to the first three lines of front matter, Jekyll knows to evaluate that {{site.build}} variable, and replace it with the value from _config.yml:

( function() {
  "use strict";

  const version = "v20180218";
  const cacheName = version + "::ethanmarcotte:";

  …
} );

Handy, too, when I’m defining a list of static assets that should be stored for offline access:

const staticAssets = [
  "/dist/css/main.{{site.build}}.css",
  "/dist/js/initial.{{site.build}}.js",
  "/dist/js/main.{{site.build}}.js",
  …
];

…which, as you may have guessed by now, turns into this:

const staticAssets = [
  "/dist/css/main.20180218.css",
  "/dist/js/initial.20180218.js",
  "/dist/js/main.20180218.js",
  …
];

That’s it! As I promised, nothing remotely groundbreaking here: a little _config.yml file, a pinch of front matter here and there, and I’m able to coordinate quite a bit of asset versionin’ and cache bustin’ on this tiny little website. I found these two tiny things quite useful; maybe you might, too.

Thus endeth the blog entry.