Workers with static assets - asset caching?

I have set up a React Router v7 site with CF Workers. The setup uses the static assets function in wrangler.json ("assets" parameter), which uploads all static assets that are compiled and bundled with Vite. They are all fingerprinted, so I would like to have the Cache-Control header to for example Cache-Control: max-age=31536000, immutable. However - when testing the setup, all static assets are on first load (empty cache) delivered with a response of 200 together with Cache-Control: public, max-age=0, must-revalidate - which my understanding is that Cloudflare tells the browser to not cache anything. On next refresh, the browser sends with a If-None-Match: ETag header in the request - and Cloudflare responds with a 304, which causes the browser to use the in-memory version of the asset. To me, this seems like the static assets are just being cached by "luck"? If the browser had not cached assets regardless of cache-control header, no static assets would be cached? I also tried to set up a cache control rule on the domain on the URI path /assets/* to override the cache header for Edge TTL and Browser TTL to 1 year. Nothing changes in the Cache-Control header due to this. Any suggestions on what I am doing wrong? Cloudflare Dashboard reports 0.5%-3% of requests are being cached over past 1-30 days, so this worries me to not get "right" before launching the site to the public - a lot less than what I would expect for a site that will be 99% static.
10 Replies
Walshy
Walshy•2mo ago
Workers Assets is already caching assets, unfortunately it just doesn't reflect in the zone analytics but be rest assured we are. We also do indeed make use of etags for browser caching, the way it's currently setup is the browser will cache but make sure to check-in with the server that it's cached value is the one we expect. Otherwise you could end up with old stale assets being served which is especially bad for html files, less bad for js but it depends on how it's being named (is it content hashed)
svend
svendOP•2mo ago
Thanks for the quick reply! Good to hear that you are caching the assets (on the edge I assume), but it would be even better if there is a mechanism to tell the browser to cache the assets. Relying on the browser incidentally still having the file in-memory to use ETags seems.. iffy? In my case, all static assets are content hashed / fingerprinted.
Walshy
Walshy•2mo ago
You can invoke your Worker and set a cache-control header. Us as a platform doing it by default isn't a great idea because it can cause problems (assets being stale) The current etag mechasism is native browser supported and still very fast
svend
svendOP•2mo ago
Yes thought about it, and not going down that road 😹 Not sure I am able to bring my point across here - but the way I understand it, the current ETag mechanism only works because the browser chose to save a copy of the assets on its own initiative after the first request to the site - even if the Cache-Control header told the browser to not cache the asset. I have no control of how long that cache is kept - could be until next browser restart, 5 minutes - who knows?
Walshy
Walshy•2mo ago
on its own initiative
that's just the way etag works, it isn't required to send a cache-control header, cache-control is a different mechanism which can accompany. Cache-Control would mean the browser would not check with the server to know if the one it has is correct, so if it cached let's say index.html - the browser could serve a stale version while the server wants to serve the fresh one. Etag explicitly caches but does a "is this still correct" check with the server - it's why we implemented this 🙂 I'm not sure how long Chrome keeps it without additional info like a cache-control header, i assume it falls back to some default time. All I'll really say is it's hard to get the balance right here, we want fast but we also need to make sure things don't break Happy to hear suggestions if we can improve this without breaking. Not sure what a Cache-Control with always revalidate would be like, I think it'd be requesting the full body each time (essentially just voiding the browser cache)
svend
svendOP•2mo ago
"Cache-Control with always revalidate " is exactly what Cloudflare is responding with today and partially why I am a bit concerned and reaching out here 🙂
No description
svend
svendOP•2mo ago
One "good enough" solution would be to have the "Caching / Cache Rule" setting actually take effect so that I could manually set up some rules. The attached rules seem to have no effect from what I could see.
No description
svend
svendOP•2mo ago
Another "good enough" solution would be to start using the _headers file support in CF Pages also for Worker Assets: https://developers.cloudflare.com/pages/configuration/headers/
divby0
divby0•2mo ago
I see the same thing and I guess many people who built stuff with frameworks to deploy to workers (instead of pages now) will be disappointed that their immutable hash-named assets will now ALWAYS be refetched. react-router also puts a _headers file that is totally ignored, probably because it was ported from Pages.
zsmooth
zsmooth•2mo ago
yeah, this is a bummer. i understand why workers isn't automatically telling browsers to cache forever, but i really wish they'd port the _headers over from pages so we can do it ourselves when we know it's safe I'll probably end up forcing assets through the worker so I can add the headers myself, but it bums me out 🙂

Did you find this page helpful?