https://github.com/acoshift/http-caching-guide
Short Guide for Modern HTTP Caching
https://github.com/acoshift/http-caching-guide
Last synced: 4 months ago
JSON representation
Short Guide for Modern HTTP Caching
- Host: GitHub
- URL: https://github.com/acoshift/http-caching-guide
- Owner: acoshift
- Created: 2018-10-01T03:22:20.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-11-04T16:04:47.000Z (over 7 years ago)
- Last Synced: 2025-02-01T02:20:24.201Z (over 1 year ago)
- Homepage:
- Size: 15.6 KB
- Stars: 26
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# http-caching-guide
Short Guide for Modern HTTP Caching
## Cache-Control
Controls how responses should be cached.
### Directives
#### no-store
Do NOT cache the response.
```text
Cache-Control: no-store
```
#### no-cache
Revalidate cache before use (see [Cache Revalidation](#cache-revalidation) for more info).
Browser will send a request to validate if the cached data can be used.
This can reduce bandwidth but still requires a roundtrip to validate the cached response.
```text
Cache-Control: no-cache
```
#### max-age
Set the maximum amount of time (in seconds) that the resource will be cached.
Browser will use cached response without sending any request (from disk cache).
```text
Cache-Control: max-age=3600
```
#### public
Response can be cached in shared cache (Reverse Proxy, CDN, etc.)
> Note: most of the time, you don’t need to use `public` as it can be inferred by other caching directives, such as `max-age`. But check with CDN document first.
```text
Cache-Control: max-age=3600
```
equals to
```text
Cache-Control: public, max-age=3600
```
#### private
Response is intended for one user CAN NOT be cached in shared cache.
```text
Cache-Control: private, max-age=3600
```
#### immutable
Prevents cache revalidation when clicking Refresh button (which normally causes revalidation on all resources).
```text
Cache-Control: max-age=31536000, immutable
```
### Cache-Control Summary
#### Static files with unique file name (ex. with hash in file name)
```text
Cache-Control: public, max-age=31536000, immutable
```
#### MPA (generate HTML)
```text
Cache-Control: no-store
```
Why not `no-cache` ?
Because MPA server usually send `Set-Cookie` to rolling cookie expiration time,
and `304 Not Modified` should not send other header than cache information.
[RFC 7372 - Section 4.1](https://tools.ietf.org/html/rfc7232#section-4.1)
#### Web Pages (static HTML)
```text
Cache-Control: no-cache
```
#### SPA index.html
```text
Cache-Control: no-cache
```
## Cache Revalidation
> Last-Modified and ETag can be used for conditional requests, but not included in this article.
When `no-cache` directive is used,
at least one of these headers must be set to trigger cache revalidation.
### Last-Modified
Time that the resource has been last modified.
Normally used for static files.
```text
Last-Modified: , :: GMT
```
ex.
```text
Last-Modified: Tue, 18 Sep 2018 11:12:03 GMT
```
If browser has cached the response, it will send a request to validate cache with
```text
If-Modified-Since: Tue, 18 Sep 2018 11:12:03 GMT
```
If the server has a newer file, then it sends the new file contents and new `Last-Modified` header
```text
HTTP/1.1 200 OK
Date: Tue, 18 Sep 2018 22:00:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 7
Last-Modified: Tue, 18 Sep 2018 20:00:00 GMT
Content
```
If file has not been modified since, then it returns 304 status code without body.
```text
HTTP/1.1 304 Not Modified
Date: Tue, 18 Sep 2018 22:00:00 GMT
```
### ETag
Like `Last-Modified` but `ETag` has more accuracy.
Used when server does not know resource's last modified date or when a resource could change more than once in a second.
ETag is like a fingerprint of resource, and a server must generate a new ETag when the resource’s contents changed.
ETag can be generated using hash of response body, UUID, or anything that results in a unique string when resource contents changed.
Browser will send `If-None-Match` to server to validate cache.
ETag has `Weak` and `Strong` validator.
#### Weak
A weak ETag is used to validate only **body** of response, when response body changed, ETag value will change.
```text
ETag: W/"value"
```
Example
```text
ETag: W/"abcde"
```
#### Strong
A strong ETag is used to validate **both** response **body** and **headers**.
Even if body is not changed but header is changed, a strong ETag must be changed to a new value.
Use-cases: To cache byte-range response.
```text
ETag: "value"
```
Example
```text
ETag: "abc1" # for gzip
ETag: "abc2" # for br
```
#### Comparison
| ETag 1 | ETag 2 | Strong Comparison | Weak Comparison |
|--------|--------|-------------------|-----------------|
| W/"1" | W/"1" | no match | match |
| W/"1" | W/"2" | no match | no match |
| W/"1" | "1" | no match | match |
| "1" | "1" | match | match |
(from [RFC-7232](https://tools.ietf.org/html/rfc7232#section-2.3.2))
#### ETag Summary
Use **Strong** ETag unless you know what you're doing 😁
Ex. you don't care about
- `Content-Encoding`
- `Content-Language`
- `Range`
- `Set-Cookie`
- `Vary`
- etc.
then you can use **Weak** ETag