Making CSS URL Unique

I already wrote how I switched to 11ty. For most of time, I am still in the honeymoon phase. Essentially the only major issue (still) remaining is missing public comment system. Whether I will solve this or not, remains to be seen.

But the most annoying issue for me was not really 11ty’s fault. At least not completely. It was more interaction between 11ty, CloudFlare caching layer, and my caching policies.

You see, for site’s performance, it’s quite beneficial to server CSS files from cache whenever possible. If you can cache it, you don’t need to transfer it. That means site is that much faster. And that is good.

However, due to multiple reasons that include preloading and long life I give to CSS files, this also means that my CSS changes don’t always propagate immediately. And thus, my CSS changes would occasionally work just fine locally, only to be invisible on public internet. At least until cache expires or all layers agree that loading the new version is in order.

My workaround was simple - every time I significantly changed CSS file, I would also change its name, thus forcing the update. But I wanted something that can be more easily automated. So, I decided to use query string.

My site doesn’t really use any query strings. But caching layers don’t know that. If they see a file with a new query string, they will treat it as a completely new cache entry. So, I added a step to my build process that will add random query string to each CSS file. Something like this:

CSS_UNIQ=$(date +%s | md5sum | cut -d' ' -f1)
find ./_site -type f -name "*.html" -exec \
  sed -Ei 's|(link rel="stylesheet" href="/\S+\.css)"|\1?id=$CSS_UNIQ"|g' {} +

This step comes after my 11ty site has already been built. My unique ID is just a current time. In order to make it a slightly obscure, I hash it. For caching purposes, this hasing is completely unnecessary. But, to me, seeing hash instead of integer just looks nicer so I use it. You can use whatever you want - be it git commit, hash of a CSS file (not a bad idea, actually), or any other reasonably unique source. Remember, we don’t really need to have it cryptographically secure - just different from run to run.

With ID in hand, using find, we go over each .html file and update its CSS links. This is where sed comes in - essentially any CSS that is part of a link element will just ?id= appended to it.

This code can be improved. One example already mentioned is tying ID to a hash of CSS file. Another might be just not updating ID if CSS files haven’t changed. And probably many more other optimizations that will help. But this code is a good starting point that can be adjusted to fit your site.