cache 功用
相同的資料不用重新抓,省時省流量
cache 設定
Stop using (HTTP 1.0) | Replaced with (HTTP 1.1 since 1999) |
---|---|
Expires: [date] | Cache-Control: max-age=[seconds] |
Pragma: no-cache | Cache-Control: no-cache |
http 1.0 的快取方式
- Pragma
- Expires
為了兼容,大部分網站還是會放
Pragma: 禁用快取
1 | // 直接放在 meta 標籤中 |
no-cache: 告訴客戶端不要對該資源快取
但受限於僅 IE 可用、僅限頁面而頁面上資源不受影響,基本上沒什麼用
與 Cache-Control: no-cache 功能一樣
Expires: 啟用快取並設定快取時間
1 | <meta http-equiv="expires" content="mon, 18 apr 2016 14:30:00 GMT"> |
若 Pragma 和 Expires 同時出現,則 pragma 優先級更高
http 1.1 新增 Cache-Control
由於 expire 無法保證 client 端時間和 server 端時間統一,http 1.1 新增 Cache-Control
若同時出現 Pragma、Expires 和 Cache-Control,Cache-Control 優先級更高
此部份分成三種快取方案
- 資源是否要快取
- 快取多久
- 到期後如何判斷是否過期
資源是否要快取
1 | cache-Control: no-store/no-cache |
no-store: 每次都去 server 要新資料,不存任何快取
no-cache: 快取需存取,但每次都去 server 檢查快取
沒有提供: 都存
private: 只有 client 可以存快取,proxy 不行
public: 大家都可以存
快取多久
1 | Cache-Control: max-age=31536000 |
max-age 與 expire 都是決定要快取多久,在時間以內則直接使用快取
browser 使用快取回應 Status code 200 (from memory cache)
注意 no-cache 不能和 max-age 一起搭配使用,no-cache 行為上與 max-age=0 相同,等於此資源在使用快取前須去 server 檢查有沒有新版本,不過還是有差
沒有設定 max-age 或 expire 的話
- 有設定 Last-Modified: expire = 當前時間+(request date-lastModified) * 10%
- 也沒有設定 Last-Modified: 都沒有= =就存不住阿
到期後如何判斷是否過期
當 browser 判斷快取已過期(max-age 時限超過),則會發 requet 跟 server 要新檔案
但是要是該檔案根本沒更新,可以繼續使用原來的快取呢?
這時就會用到 Last-Modified 與 ETag 來判斷檔案的是否更新
Last-Modified
當第一次清求資源時,response header 會設定 Last-Modified
1 | Last-Modified: Fri, 25 Feb 2021 01:47:00 GMT |
當第二次請求該資源,則 request 會帶上 If-Modified-Since
1 | If-Modified-Since: Fri, 25 Feb 2021 01:47:00 GMT |
如果該時間與 server 中該資源的最後修改時間一致,表示沒有修改過,server 返回 304 Not Modified,若有修改過,則回傳新版本的檔案
小問題: 檔案如果被打開,但是在沒有修改的情況下存檔,則會更新檔案最後修改時間,這時就要用 etag 判斷
ETag
Etag 會根據檔案內容、長度等等資訊計算出 hash 值,不同 server 會有不同計算方法
在資源回傳給 client 時,response header 會設定 Etag
1 | Etag: "5d8c72a5edda8d6a:3239" |
下次請求該資源時,request header 會帶上 If-None-Match
1 | If-None-Match: "5d8c72a5edda8d6a:3239" |
如果該資源比對後 etag 若一致,則回傳 304,不一致則回傳新版本的檔案
如果同時設定 Last-Modified 與 ETag,ETag 的優先權更高
我要最即時的更新! 但是我又不想一直問有沒有新版本
以上設定雖然可行,但是有沒有可能 「只要檔案不更新,瀏覽器就不會發 Request,直接沿用快取裡的即可。只要檔案一更新,瀏覽器就要立即抓取新的檔案」(by Huli)
只要將 ETag 實作在檔案上 + max-age 即可做到,通常前端框架 build 完都會幫你加上類似 etag 的副副檔名(那個專有名詞是啥==a)
1 | <script src='script.66666.js'></script> |
1 | Cache-Control: max-age=31536000 |
推薦快取策略
好圖推薦,不過原圖似乎被撤掉了
(來源:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-tw)