148

with fetch('somefile.json'), it is possible to request that the file be fetched from the server and not from the browser cache?

in other words, with fetch(), is it possible to circumvent the browser's cache?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
cc young
  • 18,939
  • 31
  • 90
  • 148
  • 1
    Do you have a reference for *fetch* in the [*ECMA-262 ed 6 draft*](https://people.mozilla.org/~jorendorff/es6-draft.html)? I don't see it. Or do you mean the [*WHATWG Fetch living standard*](https://fetch.spec.whatwg.org)? – RobG Mar 25 '15 at 02:46
  • RobG - using https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent – cc young Mar 25 '15 at 03:29

4 Answers4

188

Easier use of cache modes:

  // 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 */ });

  // Download a resource with cache busting when dealing with a
  // properly configured server that will send the correct ETag
  // and Date headers and properly handle If-Modified-Since and
  // If-None-Match request headers, therefore we can rely on the
  // validation to guarantee a fresh response.
  fetch("some.json", {cache: "no-cache"})
    .then(function(response) { /* consume the response */ });

  // Download a resource with economics in mind!  Prefer a cached
  // albeit stale response to conserve as much bandwidth as possible.
  fetch("some.json", {cache: "force-cache"})
    .then(function(response) { /* consume the response */ });

refrence:https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/

MJ Vakili
  • 2,798
  • 1
  • 19
  • 25
  • 1
    This is a more appropriate answer. You can handle headers like 'If-Modified-Since' and 'If-None-Match' by these options. – Nigiri Mar 15 '17 at 07:57
  • 10
    This seems to work in Firefox (54) but not Chrome (60). burningfuses's answer does work. – Scimonster Aug 15 '17 at 12:10
  • 3
    I have tested it, and as for today (November 2019) this method seems to be working on Opera, Chrome and FireFox on both Windows, Linux and Android. The burningfuses method fails at least on Opera. – Sopalajo de Arrierez Nov 27 '19 at 15:09
  • In my case it did not force cache reload until I additionally specified `pragma: no-cache` – Klesun Dec 30 '19 at 13:40
  • 2
    This respects CORS unlike the winning answer. – skrat Dec 15 '20 at 02:55
  • Yes the accepted answer does not work if CORS blocks the various headers or if the server does not support CORS at all. – Frank Weindel Dec 13 '21 at 20:55
  • Well, I never tried `no-store` due to the existence of `no-cache` . These names are a bit counter-intuitive. – li ki Sep 12 '22 at 07:03
  • 1
    You may like to read [HTTP caching - HTTP | MDN](https://developer.mozilla.org/docs/Web/HTTP/Caching). – li ki Sep 13 '22 at 16:55
  • How do I modify the headers of an existing request? – france1 Oct 07 '22 at 11:16
152

Fetch can take an init object containing many custom settings that you might want to apply to the request, this includes an option called "headers".

The "headers" option takes a Header object. This object allows you to configure the headers you want to add to your request.

By adding pragma: no-cache and a cache-control: no-cache to your header you will force the browser to check the server to see if the file is different from the file it already has in the cache. You could also use cache-control: no-store as it simply disallows the browser and all intermediate caches to store any version of the returned response.

Here is a sample code:

var myImage = document.querySelector('img');

var myHeaders = new Headers();
myHeaders.append('pragma', 'no-cache');
myHeaders.append('cache-control', 'no-cache');

var myInit = {
  method: 'GET',
  headers: myHeaders,
};

var myRequest = new Request('myImage.jpg');

fetch(myRequest, myInit)
  .then(function(response) {
    return response.blob();
  })
  .then(function(response) {
    var objectURL = URL.createObjectURL(response);
    myImage.src = objectURL;
  });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ES6</title>
</head>
<body>
    <img src="">
</body>
</html>
starball
  • 20,030
  • 7
  • 43
  • 238
burningfuses
  • 1,779
  • 1
  • 11
  • 11
  • 7
    What about using `new Request` and passing some argument to the `cache` options? I am trying to use that, but it does not work. – Mitar Jan 21 '16 at 07:05
  • 1
    Does the capitalization of the headers matter? I.e. "Cache-Control" vs "cache-control". – Isaac Lyman Aug 29 '18 at 20:29
  • 5
    @IsaacLyman, although HTTP headers are case-insensitive, I suggest you follow the proposed documentation, which is: "Cache-Control". Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers – burningfuses Aug 30 '18 at 00:26
  • 1
    To add a modern tidbit: For HTTP/2 validation HTTP headers must be all lower-case. (Just the header name, not the value). I speculate the reason is that they want to eliminate the need for toLowerCase algorithms server-side, for mostly security reasons (less attack surface). – AnorZaken Jul 22 '22 at 18:21
26

None of the solutions seemed to work well for me, but this relatively clean (AFAICT) hack did work (adapted from https://webmasters.stackexchange.com/questions/93594/prevent-browser-from-caching-text-file):

  const URL = "http://example.com";
  const ms = Date.now();
  const data = await fetch(URL+"?dummy="+ms)
    .catch(er => game_log(er.message))
    .then(response => response.text());

This is just adding a dummy parameter that changes on every call to a query. By all means, if other solutions appear to work, I suggest using those, but in my tests, they did not work in my case (e.g. those using Cache-Control and pragram).

bbarker
  • 11,636
  • 9
  • 38
  • 62
  • 3
    Thank you! This is only thing that worked for me. – Dan Dec 22 '20 at 23:48
  • A bit outdated but find this thread searching for the same issue The checked answer didn't work for my case (@%#$ CORS) as well? so first I take this hack/workaround but after find that it's can be done with set cache options (to 'no-store') directly as props in fetch options, not as part of a header props – Poul Sep 09 '22 at 21:15
25

You can set 'Cache-Control': 'no-cache' in the header like this::

return fetch(url, {
  headers: {
    'Cache-Control': 'no-cache'
  }
}).then(function (res) {
  return res.json();
}).catch(function(error) {
  console.warn('Failed: ', error);
});
Agu Dondo
  • 12,638
  • 7
  • 57
  • 68