I ran https://simonwillison.net/ through PageSpeed Insights and it warned me that my static assets were not being served with browser caching headers:
I serve static assets for my blog (mainly images) from static.simonwillison.net
, which is an AWS S3 bucket served via Cloudflare.
I investigated with curl -i
:
curl -I https://static.simonwillison.net/static/2024/prompt-gemini-extract.gif
HTTP/2 200
date: Wed, 23 Oct 2024 20:02:52 GMT
content-type: image/gif
content-length: 160263
x-amz-id-2: LpMSRQox/dMz/qS2p2jb6OmP7/YsEa4YZnOfEVgB5biGOPynNxqs8eY5EgWW0xzbclBnOI6LTAQ=
x-amz-request-id: BK8F63EJYFP5K1YB
last-modified: Wed, 23 Oct 2024 18:18:49 GMT
etag: "38a67c2deb66fe4b6f57796c2f2f5c44"
cf-cache-status: HIT
age: 149
accept-ranges: bytes
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=xu4hL1Hr5W2ZDo6VSCd4NBfPp2tmCYiTNbct64mFfU6AAkBofX%2BHSZ6P%2FpIo3QKX5CqweeBhgS%2BYNOuzWW2E4pb4O3V1pISkOHzU0NPM%2B9QgGyuquDc%2FOl2aZM5HL3MjBPm0oKJD2AWWeyY%3D"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
server: cloudflare
cf-ray: 8d7453c3481b9e5e-SJC
alt-svc: h3=":443"; ma=86400
server-timing: cfL4;desc="?proto=TCP&rtt=23918&sent=5&recv=9&lost=0&retrans=0&sent_bytes=2907&recv_bytes=585&delivery_rate=124913&cwnd=177&unsent_bytes=0&cid=ec38180c3ba3b0e7&ts=47&x=0"
That confirms it's being served by Cloudflare that Cloudflare itself is caching the page (cf-cache-status: HIT
) - but there's no cache-control
header in there telling my browser to cache the image. This means the image is fetched again from Cloudflare every time the page loads.
I wanted a quick way to add cache-control: max-age=31536000
headers to every one of those resources. I already have a policy that I rename a file any time I upload a new version so I may as well cache everything in the browser for 31536000 (24 * 60 * 60 * 365 seconds aka a full year).
Cloudflare has a bewildering array of options these days. I asked Claude and it suggested using a "Transform Rule".
Here's the form I found in the Cloudflare dashboard for adding a new rule:
Cloudflare is configured for my entire simonwillison.net
domain with the S3 bucket configured as a proxied caching CNAME to S3.
As such, I only wanted my rule to apply to static.simonwillison.net
. I configured that using a custom filter expression of Hostname = static.simonwillison.net
.
Then I told it to add a header name of cache-control
and a value of max-age=31536000
to all matching responses.
I ran this again:
curl -I https://static.simonwillison.net/static/2024/prompt-gemini-extract.gif
And got back:
HTTP/2 200
date: Wed, 23 Oct 2024 20:07:12 GMT
content-type: image/gif
content-length: 160263
x-amz-id-2: LpMSRQox/dMz/qS2p2jb6OmP7/YsEa4YZnOfEVgB5biGOPynNxqs8eY5EgWW0xzbclBnOI6LTAQ=
x-amz-request-id: BK8F63EJYFP5K1YB
last-modified: Wed, 23 Oct 2024 18:18:49 GMT
etag: "38a67c2deb66fe4b6f57796c2f2f5c44"
cf-cache-status: HIT
age: 409
accept-ranges: bytes
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=2HCHW9L52YEhmN%2FbP1ZVxQLL%2FtLrpf5GTN1J%2B8dUnvC53hhSyW2PDiAHv%2B43DvJnsUsnrInVAxdZCgTsIfQ7JCg98jFzHMdu6xb3uOGAHPdC1aE9utyUGvAedNa6RVxO9yx30qkUSuiwR2k%3D"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
cache-control: max-age=31536000
server: cloudflare
cf-ray: 8d745a2099107ac4-SJC
alt-svc: h3=":443"; ma=86400
server-timing: cfL4;desc="?proto=TCP&rtt=23766&sent=5&recv=8&lost=0&retrans=0&sent_bytes=2907&recv_bytes=585&delivery_rate=131337&cwnd=117&unsent_bytes=0&cid=bd0475734101defd&ts=55&x=0"
Note the new cache-control:
header in there.
I then tested it in Firefox. I loaded the page, opened up the network tab in browser DevTools and hit refresh. I got this:
Note the summary that says "1.38MB / 1.62 kB transferred" - the caching is working extremely well.
I have an S3 bucket behind Cloudflare and I wanted a quick and easy way to put files online that are served with access-control-allow-origin: *
, initially so I could experiment with things like Datasette Lite and the DuckDB WASM Shell.
Created 2024-10-23T22:07:26-07:00, updated 2024-10-26T11:25:09-07:00 · History · Edit