0

Old Cache Buster techniques I have found to date are:

  1. Query String in the link src: /mstylesheet.css?cache_buster=12345
  2. Change the filename each time: /mstylesheet-12345.css
  3. Apache: Cache-Control "must-revalidate" in conjunction with no-cache

I've noticed problems with all of these where stubborn Browser caches refuse to get updated assets ?

If I've understood correctly, the browser cache appears to treat the following URLs as completely different entities ?

  • /mstylesheet.css
  • /mstylesheet.css?cache_buster=12345
  • /mstylesheet.css?cache_buster=54321

So the question is: Would the following javascript work to force an existing stylesheet, linked via a link tag, without a cache buster query string, to be updated in the browser cache ?

fetch("/mstylesheet.css",{ method: "GET",headers: {"Cache-Control": "no-cache"}});

(I'd want to have this run a one off every now and then. Not on every page load).

  • `no-cache` is server side,. if you want to control cache, rather than server side you could look into using a service worker, you decide how assets then get cached. – Keith Jan 10 '23 at 17:27
  • Can service workers also fall foul of fetch caching ? https://stackoverflow.com/a/33266296/19248673 Looks like a proposal to use cache buster query strings ? – Chris Barnes Clarumedia Jan 10 '23 at 17:43
  • Yes exactly. Service workers cache your entire application pretty heavily. In angular we have to increment the [`version`](https://github.com/MintPlayer/MintPlayer/blob/master/MintPlayer.Web/ClientApp/ngsw-config.json#L4) field in the `ngsw-config.json` and call [`SwUpdate`](https://github.com/MintPlayer/MintPlayer/blob/master/MintPlayer.Web/ClientApp/src/app/app.component.ts#L87). Don't know exactly how it's done natively however. – Pieterjan Jan 10 '23 at 17:56
  • @Pieterjan No, thats just how Angular implemented a SW, you have full control of cache in a SW, you could decide not to cache anything, or cache everything, or a combination of both with custom logic etc.. – Keith Jan 10 '23 at 19:16

1 Answers1

0

From Referrer and cache control APIs for fetch(), you want either reload or no-store to bypass the locally stored cache:

  // Download a resource with cache busting, to bypass the cache
  // completely.
  fetch("some.json", {cache: "no-store"})
    .then(function(response) { /* consume the response */ });

  // Download a resource with cache busting, but update the HTTP
  // cache with the downloaded resource.
  fetch("some.json", {cache: "reload"})
    .then(function(response) { /* consume the response */ });

This is still valid in 2023. However, the real question is whether you want to support older browsers or older or misbehaving servers which may not support these directives. A server can choose to ignore these headers or a service worker can choose to not forward your request to the server in the first place. Presumably, you're in control of both of these, so they wouldn't be an issue, but it's still worth mentioning that these standards always rely on all parts of your app and stack using them correctly.

If I've understood correctly, the browser cache appears to treat the following URLs as completely different entities ?

This is correct. At the very least, the full URL is used as the cache key. Other things may be added to the key and Chrome implemented cache partitioning meaning that different origins usually don't share their cache, even if it's the exact same URL.

fstanis
  • 5,234
  • 1
  • 23
  • 42