statiqdev / Website

Code for the statiq.dev website, built with Statiq.
MIT License
21 stars 34 forks source link

No caching on statiq.dev #63

Open ociaw opened 1 year ago

ociaw commented 1 year ago

I noticed that none of the assets or mirrors are cached on statiq.dev, so big things like mermaid.js are being downloaded on every single request, which can take a while on slower connections (crappy cellular/satellite). These are all the uncached requests when hitting the home page a second time:

Screenshot of a Firefox network log. The requests are sorted by transfer size, with the the largest being mermaid.min.js with 329 kilobytes transfered.

It looks like the cache-control header for the whole site is public, max-age=0, must-revalidate - I'd suggest caching everything for at least a couple hours by default, and stuff under /mirror for a fairly long time (months?), since those libraries are inherently versioned.

daveaglick commented 1 year ago

Interesting find - the site is hosted on Netlify so these are their default headers (I don't edit them, at least not right now).

I found this article on the Netlify site about the cache-control header they use: https://www.netlify.com/blog/2017/02/23/better-living-through-caching/

It looks like they're relying on the etag and conditional caching to provide rapid cache invalidation when (and only when) the content changes:

"etag" = a version hash, which we send with all content, that the browser provides BACK to our servers when it tries to re-fetch one of these resources (as you saw above — we’ll always set assets to require re-fetching). A browser tries a conditional get in this situation, providing the etag with the initial request to let our server confirm that this version is still current if the etag we would serve with the new content matches, our server returns an HTTP 304 which allows the browser to use its cached content instead of the client having to re-download the content.

So what's especially interesting here is that your browser doesn't seem to be honoring the intent of this caching behavior - I.e. you're requesting the mermaid.min.js file over and over, even though the previous one fetched should have the same etag.

In my own browser I can see the etag header being sent: image

Is it possible yours is actually just transfering the headers and not the whole file too? I see the amount transferred in your screen shot is much lower than the actual size of the content (which I assume means the browser cache is filling in the file content itself).

ociaw commented 1 year ago

It's definitely not just headers - I think the difference between transferred and actual size is due to compression. I see that Firefox is sending a new/unique etag for each request, so it doesn't seem to care to cache it at all.

Interestingly, I just tried it on a clean Firefox profile and it seems to cache everything as expected, and the etag works correctly. I'm guessing it's something to do with my extensions or settings? I'll play around with it more and see if I can narrow down the cause.