My wasteful cacheless serving
Post #10 published on by Tobias Fedder
I am sorry. Out of thoughtlessness and lazyness, I wasted our collective resources.
Setting up directives regarding caching has been on my ToDo list for this site from the very beginning. It didn't strike me as an absolute necessity for running a blog though. Instead it's one of many tasks for the time after the launch. Also, in my head, the topic of caching has been linked to bundling CSS and JS, as well as the hashing of such static assets for cache busting. But that takes time — not necessarily a lot of time, but — more time then I could find for it this year.
I will eventually get to it, but other things popped up that I want to write about — ideally before all memories fade away; therefore before I get my CSS in order. So far tiny bits of CSS are just stuffed in the <head>
of each page. But there is one asset that's been here from the very beginning — apparently an indispensable part of my minimum viable blog. That asset is the icon, the icon for your favorite bookmarks, the favicon, only provided as a SVG, meant to display my initials (because this site is about me, me, me).
Without the caching set up though, that led to our user‐agents making up to two HTTP requests for every navigation on my site. Sure, it's really so important to me that you have to download it in the first place, but exactly one time is good enough, because I'm not planning on changing it. Yet, out of negligence on my part, our user‐agents made almost twice as many request as necessary. Hurting the people the most who use this site the most — probably myself.
In case you're wondering about the number of request being up to two
, not exactly two, that's due to the presence of the Last-Modified
header. Your browser most likely guessed the asset was good to use for a while after the last request. Good for a tenth of the time since the asset has last been modified at the time of the last actual request.
Now I fixed it. The following addition to my Caddyfile leads to all files under /assets/
being served with the bold claim they'd be good to use for two years. So good in fact, the user‐agent shouldn't even check on reloads — that's the immutable
part.
⋮
header /assets/* {
Cache-Control "public, max-age=63072000, immutable"
}
⋮
While I was on it I thought that the content itself doesn't change that often either. In case someone is navigating back and forth, do they really need to request the HTML each time? I don't think so. Let's give possibly — but unlikely — outdated pages up to five minutes to live.
⋮
@html file {path}/index.html
⋮
header @html {
Cache-Control "public, max-age=300"
}
⋮
Above I defined a matcher called html
that checks if a file named index.html
exists in a directory that reflects the requested path. That's the way Eleventy outputs my files. If so, then the Cache-Control
header will be added to the response.
And that's how I built yet another footgun. Let's hope I remember changing the filenames of any assets I add, before I set up a build system that adds hashes to assets' filenames automatically.