Busting Your Cache with the Power of Git

I've been using middleman since 2012. While working on the current redesign, I once again encountered the problem that I had no way of busting the cache, especially for CSS files.
While Middleman provides handy tooling for cache busting, I have not been using it because I've been trying to slowly wean my layouts away from using Middleman/Sinatra-specific helpers so that if I decide to move to a different static-site generator. ¯(°_o)/¯
I decided to tackle it by hand, because why not. My first try was naive to say the least.
commit 1517eabb35fe34b6d2aac4150649798658d5c6f5
Author: Evan Travers <[email protected]>
Date: Wed May 20 09:17:56 2020 -0500
Try adding a cachebreaker
diff --git a/source/layouts/layout.html.erb b/source/layouts/layout.html.erb
index ae25085..b68fe67 100644
--- a/source/layouts/layout.html.erb
+++ b/source/layouts/layout.html.erb
@@ -37,7 +37,7 @@
<link href="https://fonts.googleapis.com/css?family=Muli:300,400,400i,700|Literata:700,300&display=swap"
rel="stylesheet">
- <link rel="stylesheet" href="/dist/style.css">
+ <link rel="stylesheet" href="/dist/style.css?cachebreaker=<%= Time.now.to_i %>">
</head>
<body>
<nav class="main_navigation">
It first appeared to work... but do you see my mistake? When Middleman builds each file, Time.now.to_i
is still ticking away. Every file will get a totally different cache-breaker! While each refresh will indeed get a fresh file, every page will re-request the css file. That's not right at all.
I realized that I needed to only change the URL when the CSS file changes. What system do I have in place that tracks changes? Source control!
commit 7ec5bc915bc78735f43ffedd8660763b73cd1c6d
Author: Evan Travers <[email protected]>
Date: Wed May 20 09:28:02 2020 -0500
More intelligent cachebreaker
This one will only update if I update the style.scss file, and it'll be
the same on _every_ page.
diff --git a/config.rb b/config.rb
index 72d2be8..8d0b238 100644
--- a/config.rb
+++ b/config.rb
@@ -50,6 +50,10 @@ helpers do
'evantravers.com'
end
+ def style_cache_id
+ `git log --pretty=format:'%H' -n 1 -- source/css/style.scss`
+ end
+
def meta_description
if is_blog_article?
Sanitize.clean(current_page.summary).strip
diff --git a/source/layouts/layout.html.erb b/source/layouts/layout.html.erb
index ae25085..4904350 100644
--- a/source/layouts/layout.html.erb
+++ b/source/layouts/layout.html.erb
@@ -37,7 +37,7 @@
<link href="https://fonts.googleapis.com/css?family=Muli:300,400,400i,700|Literata:700,300&display=swap"
rel="stylesheet">
- <link rel="stylesheet" href="/dist/style.css">
+ <link rel="stylesheet" href="/dist/style.css?cachebreaker=<%= style_cache_id %>">
</head>
<body>
<nav class="main_navigation">
So far, this works wonderfully. If I push an update without any CSS changes, no files change, and you get the benefit of the existing cache. If I push any change to the CSS file, every single page on the site gets a new URL for the style, forcing the cache to refresh. I do a little more file-moving and computation, but the user doesn't feel the pain.
Simple, but it works.
Changelog
-
2022-06-08 11:31:29 -0500Rename articles
-
2020-06-18 14:26:02 -0500Move everything to CST
Don't know why I didn't do that before. It caused _no_ end of
problems. -
2020-05-27 20:32:37 -0500Title case the title
-
2020-05-27 20:29:15 -0500Post: Busting cache