第一次請求了 100 個檔案, 再次訪問的時候,如果全部重新請求, 非常浪費時間, 也很笨拙.
分析:
因為有些檔案, 在使用者的多次請求中, 都是相同的, 如果多次請求都重複請求這個檔案, 無疑是一種浪費.
那麼就想到了快取: 把資源快取到本地, 再次請求的時候直接使用本地的快取檔案.
走極端:
把所有的檔案都快取起來.
分析:
這樣也不行, 因為在請求過來的 100 個檔案中, 可能有一部分是長久不變的, 有一部分是隔一段時間就變的,
還有的檔案是每次都不一樣的.
那麼怎麼辦?
要區分這些檔案, 快取的主動方(瀏覽器) 說: 我要知道我要不要快取一個檔案, 我要知道下次請求的時候對於
某個檔案我到底能不能直接用快取, 還是需要重新請求.
OK.
伺服器說: 那我跟你說每個檔案的你要不要快取, 什麼時候不能用快取.
然後伺服器就在響應的時候, 新增一個響應頭 Expires
類似這樣:Expires: Thu, 01 Dec 1994 16:00:00 GMT (必須是GMT格式)
瀏覽器得到這個檔案之後, 先使用這個檔案.
過了一會使用者重新請求了
瀏覽器把 Expires 標記的時間 a, 和當前請求的時間 b 做個對比, 如果是這樣
a....b // 說明過期了, 那麼就重新請求
b....a // 咦還沒過期, 還能吃
與 Expires 有同樣功能的還有 Cache-Control, Parama 等響應頭
Cache-Control 是 HTTP 1.1 提出的, Expires 是 HTTP 1.0 提出的, 前者比後者優先順序高–在同時使用的時候.
…
然後, 瀏覽器發現不對, 這個檔案過期了, 我重新拿過來的怎麼還是和過期的一樣, 你丫騙我.
伺服器說: 那我能怎麼辦, 你又要過期時間, 還不能不給, 那哪能每個檔案的過期時間我都能精確算出來, 那個檔案明明我覺得
它經常變, 誰知道它一直都不變.
OK.
伺服器給出了個解決方案:
你看這樣, 我呢, 把每個檔案算出來一個值, 只要檔案變化了, 這個值就會改變. 然後把這個值扔給你。
你如果發現快取過期了, 請求的時候把這個值也給我.
我來看看這個值和我這邊的值是不是一樣的
如果是一樣的, 那麼說明這個檔案沒有變對不對, 那我就不給你檔案了,給你一個 304 你再繼續使用快取檔案
這個值使用 Etag 來標記,
客戶端在快取過期重新請求的時候, 加上一個頭 If-None-Match:(Etag的值)
OK.
伺服器又說了, 哎這樣的話我還想到另外一種方案
我給你檔案的時候標記一下這個檔案最後修改的時間, 你要是發現快取過期了, 重新請求的時候把這個時間給我
我比較一下我這邊記錄的最新的檔案更改時間, 如果兩個相同不就說明檔案沒改, 對不對.
伺服器給客戶端的時間叫: Last-Modified
客戶端返回過來的是: If-Modified-Since(Last-Modified 的值)