Skip to content

Commit 9e783da

Browse files
committed
Added stale directives
For edge cases and better cache hit ratio of unsupporting browsers
1 parent 77aa31a commit 9e783da

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

README.md

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@
55

66
This tiny NGINX module can help improve caching of your public static assets, by setting far future expiration with `immutable` attribute.
77

8+
## Intended audience
9+
10+
Websites and frameworks which rely on the cache-busting pattern:
11+
12+
* static resources include version/hashes in their URLs, while never modifying the resources
13+
* when necessary, updating the resources with newer versions that have new version-numbers/hashes,
14+
so that their URLs are different
15+
16+
Popular frameworks which use cache-busting:
17+
18+
* Magento 2
19+
* Include your own here!
20+
821
## Synopsis
922

1023
```
@@ -21,38 +34,73 @@ will yield the following HTTP headers:
2134

2235
```
2336
...
24-
Cache-Control: public,max-age=31536000,immutable
37+
Cache-Control: public,max-age=31536000,stale-while-revalidate=31536000,stale-if-error=31536000,immutable
2538
Expires: Thu, 31 Dec 2037 23:55:55 GMT
2639
...
2740
```
2841

2942
How it's different to `expires max;`:
3043

31-
* Sets `immutable` attribute, e.g. `Cache-Control: public,max-age=31536000,immutable` for improved caching
44+
* Sets `immutable` attribute, e.g. `Cache-Control: public,max-age=31536000,immutable` for improved caching.
45+
That is 1 year and not 10 years, see why below.
3246
* Sends `Expires` only when it's really necessary, e.g. when a client is requesting resources over `HTTP/1.0`
3347
* Sets `public` attribute to ensure the assets can be cached by public caches, which is typically a desired thing.
3448

35-
Thus, in most cases, `immutable on;` can be used as a better alternative to `expires max;`.
49+
Due to the [lacking support of `immutable`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#browser_compatibility) in Chromium-based browsers,
50+
we also add `stale-while-revalidate=31536000,stale-if-error=31536000` which helps to improve cache hit-ratio in edge cases.
51+
Use of these directives allows serving cached responses beyond their cache lifetime, which is forever in case of immutable resources.
52+
53+
Thus, in most cases, `immutable on;` can be used as a better alternative to `expires max;` to implement the cache-busting pattern.
54+
55+
### Why 31536000 seconds (1 year?)
56+
57+
The [RFC](https://www.ietf.org/rfc/rfc2616.txt) defines to use one year to make a response as "never expires":
58+
59+
> To mark a response as “never expires,” an origin server sends an
60+
> Expires date approximately one year from the time the response is
61+
> sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
62+
> year in the future.
63+
64+
More details in [the article](https://ashton.codes/set-cache-control-max-age-1-year/).
3665

3766
## Installation
3867

39-
### CentOS/RHEL 6, 7, 8; Amazon Linux 2; Fedora Linux
68+
GetPageSpeed provides packaging of the `nginx-module-immutable` in its repositories, as part of its [NGINX Extras](https://nginx-extras.getpagespeed.com/) package collection.
4069

41-
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
42-
sudo yum -y install nginx-module-immutable
70+
The follow operating systems are supported:
71+
72+
* RedHat Enterprise Linux 6, 7, 8, 9
73+
* CentOS 6, 7, 8, 9
74+
* AlmaLinux 8, 9
75+
* Rocky Linux 8, 9
76+
* Amazon Linux 2
77+
* Fedora Linux, the 2 most recent releases
78+
79+
The installation requires a [subscription](https://www.getpagespeed.com/repo-subscribe) for all the operating systems listed, except Fedora Linux, for which it is free.
80+
81+
### How to install
82+
83+
For any OS listed above, installation steps are the same:
84+
85+
```bash```
86+
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
87+
sudo yum -y install nginx-module-immutable
88+
```
4389
4490
Follow the installation prompt to import GPG public key that is used for verifying packages.
4591
4692
Then add the following at the top of your `/etc/nginx/nginx.conf`:
4793
48-
load_module modules/ngx_http_immutable_module.so;
94+
```nginx
95+
load_module modules/ngx_http_immutable_module.so;
96+
```
4997

5098
## Example: Magento 2 production configuration
5199

52100
Provided that your store runs in production mode, you have already compiled all the assets.
53101
This [sample config](https://github.com/magento/magento2/blob/2.3.4/nginx.conf.sample#L103-L134) can be optimized to:
54102

55-
```
103+
```nginx
56104
location /static/ {
57105
immutable on;
58106
@@ -75,7 +123,7 @@ location /static/ {
75123

76124
When used together with [`ngx_security_headers`](https://github.com/GetPageSpeed/ngx_security_headers), it can be simplified further:
77125

78-
```
126+
```nginx
79127
security_headers on;
80128
81129
location /static/ {

src/ngx_http_immutable.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@ ngx_http_immutable_filter(ngx_http_request_t *r)
185185
}
186186
#endif
187187

188-
/* 10 years */
189-
ngx_str_set(&cc->value, "public,max-age=31536000,immutable");
188+
/* 1 year is the maximum allowed by spec */
189+
ngx_str_set(&cc->value, "public,max-age=31536000,stale-while-revalidate=31536000,stale-if-error=31536000,immutable");
190190
}
191191

192192
/* proceed to the next handler in chain */

t/cc.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ __DATA__
1616
--- response_body
1717
hello world
1818
--- response_headers
19-
Cache-Control: public,max-age=31536000,immutable
19+
Cache-Control: public,max-age=31536000,stale-while-revalidate=31536000,stale-if-error=31536000,immutable
2020

0 commit comments

Comments
 (0)