Force use of HTTP Cache with fetch
Asked Answered
G

1

6

I'm trying to use the HTTP Cache for something simple, but I can't get it to work.

I'm using the following options for fetch().

fetch('test', {
        cache: 'force-cache',
        headers: {
            'Cache-Control': 'max-age=3600',
            'Pragma': 'max-age=3600', // added for redundancy
        }
    })
    .then( response => response.json() )
    .then( data     => console.log(data) )
    .catch( error   => console.error(error) )
    .finally( ()    => console.log('Done') );

The test endpoint simply returns a json with the following format

{
    "date": "...", /* date in 'Y-m-d H:i:s' format */
}

I've made sure the response has the Cache-Control header as well. I can see it when I inspect the response headers.

HTTP/1.1 200 OK
Server: Apache
Cache-Control: public, max-age=3600
Content-Length: 30
Keep-Alive: timeout=5, max=94
Connection: Keep-Alive
Content-Type: application/json; charset=UTF-8

The request headers also seem to be correct.

Connection: keep-alive
Pragma: max-age=3600
Cache-Control: max-age=3600
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty

I tried to just run that same fetch over and over in the span of a minute, expecting to get the same date, unchanged but the results were always "new" so to speak.

Do I have a fundamental misunderstanding of how HTTP Cache works or am I better off just caching the value in the back-end?


I'm currently testing by running the following code inside a <script> tag.

let x = 0;
const interval_id = setInterval(() => {
  fetch('test', { ... });
  if (++x === 20) {
    window.clearInterval(interval_id);
  }
}, 1500);

I'm expecting to be returned the same datetime 20 times (cache the first response)

Gluck answered 17/11, 2021 at 14:59 Comment(8)
How are you fetching over and over? If it's by using reload, note that browser reload behavior isn't standardized and often ignores the cache. Try opening the same URL in a new tab instead.Ventricose
The server determines the cache headers and instructs the client how to cache the response. You can't do this on the client, although you could create your own fetch cache.Sabian
@KevinChristopherHenry I'm not reloading, just running the same fetch query over and over again in the consoleGluck
@Sabian I have control over the response (server) and its headers but that doesn't seem to be working.Gluck
@Sabian Now I've switched to using a function in a <script> tag because I thought the console could have somethign to do with the cache not being used but it still doesn't seem to be caching the response.Gluck
@Gluck If you tried this on the server, share all the details. Also note that if you have developer tools open, caching might be disabled.Sabian
It is as you say. I feel dumb. Cache was disabled in the developer tools.Gluck
@Gluck You don't have to feel dumb if you ask me :) Also didn't notice it :)Unmeant
N
1

Alternatively, if you prefer not to depend on max-age and desire to render immediately from cache, consider exploring the features of my CacheFirst library at https://github.com/lakshminathan/CacheFirst. This library utilizes localStorage and indexedDB for storage, and employs SHA-256 for comparing new and old responses, allowing you to serve cached responses instantly, and re-render only if the new response is different. This approach reduces the time that we serve stale data compared to the max-age approach.

Nich answered 29/12, 2023 at 6:3 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.