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.
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 request
no-store— This will tell any cache system not to cache the file whatsoever
max-age=0— This is also won’t cache the file
max-age=31536000— This is not a good choice for an
index.html. The value in the max-age represents seconds — in this case the file would be cached for a year
- The directive
must-revalidateis also recommended. When it is enabled, the cache must verify the status of stale resources before using them. Expired resources should not be used.
The following header could be used to disable cache for HTTP/1.0 :
Pragma: no-cache Expires: 0
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.
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.”
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 (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:
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
Not Modified status, without a body, which tells the client that the cached version of the response is still good to use (fresh).
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.
max-age headers on your JS, CSS, and any other files that change frequently