问题
I build a service worker which always responds with data from the cache and then, in the background, sends a request to the server. If the server responds with HTTP 304 - not modified
everything is fine, if the server responds with HTTP 200
, that means the data was changed and the new file is put into the cache, also the user is notified and asked for a page refresh.
I use the not-modified-since
/ last-modified
headers to make sure the client gets the most up-to-date version. When a request is sent via fetch()
the request passes the HTTP-cache on it's way to the network - also the response passes the HTTP cache when it arrives on the client. The problem is when the response has the status 304
- not modified the HTTP cache responds to the service worker with the cached version and replaces the status with 200
(as it is described in the fetch specification - HTTP-network-or-cache-fetch). In the service worker there is no possibility to find out whether the 200
response was initially sent by the server (the user needs to be updated) or it was sent by the cache and the server originally responded with 304
(most up-to-date version is already loaded).
There is the cache-mode flag which can be set to no-cache
, but this bypasses the HTTP-cache also when the request is sent to the server, which means that the if-modified-since
header is not set and the server has no chance to find out which version the client has. Also this flag is only supported by firefox nightly right now.
I think the best solution is to set a custom HTTP header like x-was-modified
when the server responds with 200
. This custom header can be accessed in the service worker and can be used to find out whether a resource was updated or not - even if the HTTP cache replaces the 304
status with 200
.
- Is this a legit solution/workaround? Are there any suggested approaches to solve this problem?
- Should I even rely on HTTP headers which are supposed to handle the HTTP cache when implementing the service worker cache? Or should I rather use custom
x-if-modified-since
/x-last-modified
headers and use indexedDB to store the information on the client and append it to each request? - Why does
fetch()
even replace the304
code with200
if there is a up-to-date version in the cache?
回答1:
You can’t rely on the status code (304 vs. 200) to determine whether something has changed. What if some other part of your code requests the same resource, thus updating the browser’s cache?
Instead, simply compare the response’s Last-Modified
header to what you sent in If-Modified-Since
, or whatever you last saw in Last-Modified
. If the values don’t match, something has changed.
For more precision (if the data can change several times in 1 second), consider using ETag instead of Last-Modified
.
Why does
fetch()
even replace the304
code with200
if there is a up-to-date version in the cache?
Because usually people just want to get fresh content, regardless of where it comes from. A 304 response is only interesting to those who implement their own HTTP caches.
来源:https://stackoverflow.com/questions/37137776/recognize-http-304-in-service-worker-fetch