在優化網頁速度時,常會使用 cache 的機制來減少 server 負載, client 資源等待時間。
比如
- server 前面會架一台 cdn 服務, cache 一些靜態檔案…等等。
- server 可能會使用 redis, 來 cache 需要做大量計算的結果,降低負載。
這篇則是要介紹有哪些 http header 可以善用在 client 端(瀏覽器)來優化網頁速度,檢查是否有成功 cache 可以參考此篇文章
-
Expires
最早在 http 1.0 就存在的 header, 使用方式為 Expires[date]
(日期格式必須符合 RFC1123)
例如: Expires: Wed, 5 Mar 2018 11:00:00 GMT
用法為設定一個確切的日期,當 client 端時間小於 response header (Expires
) 時間時,則會使用 cache.
由於 client 端的日期是跟隨作業系統的時間,因此可能因為使用者的設定不同,而不如預期的 cache,因此在 http 1.1 後建議使用 cache-control
header
根據 RFC2616 描述 Expires
header 需要注意的有以下兩點,
1. Expires
會被 cache-control
及 max-age
header 覆寫
2. 若 date 格式不符合 RFC1123 所規範之格式,等同於不 cache
3. 若 Cache-Control
header 存在並配合 max-age
設定將會 overwrite 此 header
Note: if a response includes a Cache-Control field with the max- age directive (see section 14.9.3), that directive overrides the Expires field.
-
Pragma
此 header 是在 http 1.0 時的 header, 常與 Expires
一起使用,用法為 Pragma: no-cache;
根據 RFC7234 說明此 header 等同於在 http1.1的 Cache-Control: no-cache
另外,要注意的是在 http 1.1 後當 Cache-Control header 存在時,此 header 會被忽略。
When the Cache-Control header field is also present and understood in a request, Pragma is ignored.
-
Cache-Control
此 header 為 http1.1 所定義的,整合了上面 http 1.0 的 Expires
與 Pragma
根據 RFC2616 說明此 header 定義了許多 directive,並且分為 request(client)/response(server) 不同的使用情境。
cache-control 包含了許多的 directive及概念,大體上可以參考這張圖
以下詳細介紹在 request 及 response 常見的幾個 directive
request/response:
1. private: 此 cache 是私有的,只有 client (browser) 可以儲存 cache,常用於個人化敏感資料或像是 api response。
2. public: 此 cache 為公有共享的,中間傳輸的 ISP, proxy 及 cdn 服務商都可以儲存 cache,常用於公用的靜態檔案,像是 js, css 及圖片等 asset。
3. max-age: 設定 cache 多久(秒)過期
相對於 http1.0 的 Expires
header,在 http 1.0 的 Expires 所設定的為絕對時間(e.g. Expires: Wed, 5 Mar 2018 11:00:00 GMT
),但由於 client(browser/os) 端的時間是使用者可更改的,因此可能導致 Expires
時間與 http header reponse 時間不同步造成 cache 無法如預期運作。
要注意的地方是在 RFC2616 中有提及 max-age
會覆蓋 http1.0 的 Expires
If a response includes both an Expires header and a max-age directive, the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
4. no-cache: 要使用 cache 時必須與做 revalidate,可以儲存 cache。
舉例來說當 server 設定 cache-contorl: no-cache;
時,每次發出的 request 都一定會發 request 與 server 確認是否有內容的更動,若 server 回傳 304 (Not Modified) 則使用 cache 反之則拿取新內容。
ps. 與 Pragma: no-cache;
相等
5. no-store: 不使用任何 cache,並不儲存 cache。
如上解釋,完全不使用 cache,每次都向對方拿內容。
6. no-transform: 不要對傳輸內容做任何轉碼。
常見的地方為 proxy 或 browser 為了減少傳輸內容及流量,會對傳輸的圖片格式做壓縮換轉換,此 header 可避免被轉碼。
request:
1. max-stale: 設定接受過期多久秒的 cache
舉例來說若上次 request 從 response header 得到了 Expires: Wed, 5 Mar 2018 11:00:00 GMT
,因此當我們在 2018/03/05 11:01:00 時發送 cache-control: max-stale=120
request, 由於此 cache 僅過期 60秒(<= max-stale),因此是不會真實發送 request 到 server 而是使用cache 。
除此之外,也可以設置 cache-control: max-stale
不論過期多久都使用 cache。
2. min-fresh: 設定接受在距離多久過期的 cache
舉例來說若上次 request 從 respinse 得到了 Expires: Wed, 5 Mar 2018 11:00:00 GMT
,因此當我們在 2018/03/05 10:59 分以後發送 cache-control: min-fresh=60
request 都會視為 cache 已經不新鮮而發送至 server。
response:
1. must-revalidate: 在 cache max-age
到期時,盡管有設 max-stale
延長 cache 新鮮度也應該要做 validate。
相較 no-cache
較寬鬆
2. proxy-revalidate: 設定 public cache 時 proxy 的 validate
根據 RFC2616
The proxy-revalidate directive has the same meaning as the must-revalidate directive, except that it does not apply to non-shareduser agent caches.
3. s-max-age: 設定 public cache 時 proxy 的 max-age
設定中間的 cdn, proxy 或 ISP 的 cache。
根據 RFC2616
The s- maxage directive is always ignored by a private cache.
參考資料:
https://blog.techbridge.cc/2017/06/17/cache-introduction/
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires