A cache’s primary purpose is to increase data retrieval performance by reducing the need to access the underlying slower storage layer. Trading off capacity for speed, a cache typically stores a subset of data transiently, in contrast to databases whose data is usually complete and durable.
The cache can exist at browser, CDN, load balance or many other layers.
Cache control
response header to disable cache in HTTP/1.1
Let’s assume you load a single page application. You can check whether the index.html got cached by checking the cache-control
in the response header, using web developer tools by pressing F12 in the browser.
In general, a good solution to disable browser cache for HTTP/1.1 would be:
Cache-Control: no-store, must-revalidate
cache-control
can have these values:
no-cache
— This name is a bit misleading, because it will use a cached version, but it will also check if there is a newer version on the server by validating the file’s hash on every requestno-store
— This will tell any cache system not to cache the file whatsoevermax-age=0
— This is also won’t cache the filemax-age=31536000
— This is not a good choice for anindex.html
. The value in the max-age represents seconds — in this case the file would be cached for a year- The directive
must-revalidate
is also recommended. When it is enabled, the cache must verify the status of stale resources before using them. Expired resources should not be used.
Pragma
response header for disabling cache in HTTP/1.0 and IE6
The following header could be used to disable cache for HTTP/1.0 :
Pragma: no-cache Expires: 0
The Pragma
general-header field is used to include implementation-specific directives that may apply to any recipient along the request/response chain. When the “no-cache
” directive is present in a request message, an application should forward the request toward the origin server even if it has a cached copy of what is being requested.
The Expires
entity-header field gives the date/time after which the entity should be considered stale. A value of zero (0) or an invalid date format should be considered equivalent to an “expires immediately.”
Best practice setting
Overall, the following solution could be the strictest, and also should be accepted by most of the browsers:
Cache-Control: max-age=0, no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0
ETag response header
The ETag
(or entity tag) HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed. If the resource at a given URL changes, a new Etag
value must be generated.
A typical use of the ETag
header is to cache resources that are unchanged. If a user visits a given URL again (that has an ETag
set), and it is stale (too old to be considered usable), the client will send the value of its ETag
along in an If-None-Match
header field:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
The server compares the client’s ETag
(sent with If-None-Match
) with the ETag
for its current version of the resource, and if both values match (that is, the resource has not changed), the server sends back a 304
Not Modified
status, without a body, which tells the client that the cached version of the response is still good to use (fresh).
Single page applications and caching
It is important to never cache your index.html
file, otherwise users will see the old version of your application until the browser cache expires.
Use a bundler like Webpack to implement hashed versioned file names, that means each application-build will create files that are named differently if their content changed. This is also called Filename fingerprinting.
Use no-cache
and max-age
headers on your JS, CSS, and any other files that change frequently