Cache Busting with Hugo Pipes
When I set this site up on Amazon S3 and CloudFront, I enabled caching to improve overall performance. However, caching can become an issue when you want to update files frequently — such as stylesheets — and ensure that the very latest version of that file is being served.
I knew that with CloudFront I could invalidate cached files and therefore force it to serve the latest version, but this is a slow, manual process that can also incur fees. Alternatively, I knew that I could use some form of versioned file names to ensure that the latest version of a file is being served (basically make sure the file being requested has a unique file name so that the newly updated file won’t be served from the cache), but I wasn’t sure how do this using Hugo — the static site generator behind this blog.
Enter Hugo Pipes
I’m very new to Hugo, so when I started looking for a solution, I wasn’t aware of Hugo Pipes. After much searching, I happened upon a great writeup on Hugo Pipes by Regis Philbert that explained what they are and how to use them.
Hugo Pipes are a set of functions that allow you to run processes on certain files during the build phase. As it turns out, there’s a Hugo Pipes function that’s perfect for solving this caching issue called fingerprint
.
This function allows you to add a sha256
hash to the end of a file name when it has been updated. This means that every time you update that file, it will have a unique file name, so the next time someone visits the site, the new file will be requested instead of the cached — and now outdated — version of the file.
The Solution
Here’s how I implemented fingerprint
with this site’s CSS file. I’ll break it down further below.
<head>
...
{{ $style := resources.Get "css/blog.css" | fingerprint }}
<link rel="stylesheet" href="{{ $style.Permalink }}">
</head>
First, we’re setting the file that we want to modify (in this case blog.css
) to a variable named $style
:
{{ $style := resources.Get "css/blog.css" }}
Next, we’re defining the Hugo Pipes function that we want to run on this file — in this case fingerprint
:
{{ $style := resources.Get "css/blog.css" | fingerprint }}
Finally, we pass the $style
variable as a Permalink
to our stylesheet’s <link>
element and we’re done:
<link rel="stylesheet" href="{{ $style.Permalink }}">
This results in the processed file having a unique file name like this:
<link rel="stylesheet" href="/css/blog.min.27b33892dc3fb63a8d19bbe7df41b205.css">
To learn more about Hugo Pipes and all the different functions that are available, check out the Hugo Pipes Introduction documentation.