1

We would like to know from where the initial html document itself was served, either directly from the browser cache, our cdn cache or from origin. The later are easy (since our cdn adds server-timing to indicate a cache hit/miss), but figuring out if the document was served directly from the browser turned out more difficult.

I know about developer tools/network tab and how Chrome for example can show this information, but this question is specifically about any JavaScript API that can be used to detect and report it to us.

So far I've tried three things:

  • var isCached = performance.getEntriesByType("navigation")[0].transferSize === 0; from this answer, but today this seems to report the previous transferSize. When I try the same with the latest Chrome, I never get transferSize === 0, even when the devTools show me that it was cached. Possibly it only works for other resources, but not the html document itself.

  • var isCached = window.performance.navigation.type === 2 according to this answer gets the navigation type (in this case backward/forward), which is not always a true indicator of the document being cached. E.g. clicking a link is of type navigation and can also be cached.

  • Storing the timestamp in the document itself as suggested here on the server and comparing it does not work either, especially since we are using a cdn that has its own cache. We wouldn't be able to differentiate between a cached version from cdn or the browser.

Sven
  • 2,839
  • 7
  • 33
  • 53
  • You can use a `serviceWorker`, with this you have full control of the browsers cache. https://developer.mozilla.org/en-US/docs/Web/API/Cache – Keith Nov 02 '22 at 14:49
  • I would prefer to rely on the included browser cache mechanisms and avoid having the added complexity of a dedicated `serviceWorker`, but in any case at a glance I'm not sure if this is possible for the html document itself, or as for the `transferSize` limitation, only for other resources. – Sven Nov 02 '22 at 14:55
  • https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage, you do not service worker to access this JS API, it should be accessible in the window object – Luke Celitan Nov 02 '22 at 15:00
  • @LukeCelitan You don't need a SW to access, but without a `serviceWorker` it's going to be tricky filling the cache.. :) – Keith Nov 02 '22 at 15:08
  • `await window.caches.keys()` returns `[]`, which is (I assume) because I would have to manage the cache myself, but can't see what the browser is doing? – Sven Nov 02 '22 at 15:08
  • @Sven The cache in the Service worker can cache the HTML document too, if it couldn't then offline apps wouldn't work. `returns []` yep, you need to fill the cache manually without the SW. :( – Keith Nov 02 '22 at 15:09
  • It's also good to remember that Chrome dev tools, disables cache by default, check your network tab. – Luke Celitan Nov 03 '22 at 08:21
  • 3
    Having this information doesn't seem like an end in itself... Why is it useful to you? What problem are you really trying to solve? – jsejcksn Nov 07 '22 at 08:31
  • `performance.timing.responseEnd - performance.timing.responseStart` should be precise enough to tell a disk/ram cache hit from a network load; a disk will be about 5-10ms max... – dandavis Nov 08 '22 at 06:38

2 Answers2

1

From the MDN documentation and the PerformanceNavigationTiming interface described here, we can see that :

the requestStart attribute returns the time immediately before the user agent starts requesting the current document from the server, or from the HTTP cache or from local resources

We also have at our disposal the responseStart attribute :

responseStart returns the time after the user agent receives the first byte of the response from the server, or from the HTTP cache or from local resources

So, you should be able to detect when your initial HTML Document is served from the browser cache when the timing between the requestStart and responseStart is identical or almost identical.

It will be something like the following:

const timingDelta = 10; // to be conservative, but should be less than 5ms
const performanceEntry = performance.getEntriesByName("<URL of your document>")[0]; // ex: performance.getEntriesByName("https://www.google.com/")[0];

if (performanceEntry.responseStart - performanceEntry.requestStart < delta) {
    console.log('document was served from cache');
}

// that info is also available on the performance.timing object but it's deprecated
// for your information, that would look like this:
if (performance.timing.responseStart - performance.timing.resquestStart < delta) { ... }
mlegrix
  • 799
  • 5
  • 12
0

Why not checking http response code ? Especially the 3xx codes.

304 Not Modified Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

BenoitB
  • 31
  • 6