阿里雲存儲如何讓瀏覽器始終以200 (from cache)緩存圖片?

阿里雲存儲如何讓瀏覽器始終以200 (from cache)緩存圖片?


無魚,唯漁之法也: https://www.mnot.net/cache_docs/


### HTTP緩存基礎

#### 協商緩存

- `If-Modified-Since/Last-modified`: 伺服器程序檢查請求頭(`request header`)裡面的(`If-modified-Since`),如果最後修改時間相同(例如靜態文件的Modified time 通過shell `ls -l`可以查看)則返回304,否則給返回頭(`response header`)添加`last-Modified`並且返回數據(response body)。

- `If-None-Match/Etag`:伺服器程序檢查檢查請求頭(`request header`)裡面的`if-none-match`的值與當前文件的內容通過hash演算法(`例如 nodejs: cryto.createHash("sha1")`)生成的內容摘要字元對比,相同則直接返回`304`,否則給返回頭(`response header`)添加`etag`屬性為當前的內容摘要字元,並且返回內容。

#### 強緩存(也就是題主所說的from cache)

- 如果設置了`Expires`(XX時間過期)或者`Cache-Control(http1.0不支持)`(經歷XX時間後過期)且沒有過期,命中`cache`的情況下,`from cache`不去發出請求。如果強刷(如ctrl+r)會發起請求,但是如果沒有修改會返回`304`內容未修改,如果已經改變則返回新內容。

- expires/cache-control 雖然是強緩存,但用戶主動觸發的刷新行為,還是會採用緩存協商的策略,主動觸發的刷新行為包括點擊刷新按鈕、右鍵刷新、f5刷新、ctrl+f5刷新等。

- 當然如果在控制台裡面選中了`disable cahce`則無論如何都會請求最新內容(304協商緩存、強緩存都無效),因為

1.不會檢查本地是否有緩存。

2.請求頭信息(request header)既沒有If-Modified-Since也沒有If-None-Match來讓服務端判斷。

地址欄輸入的地址按下回車鍵,該地址頁面請求(僅僅是該url)的`request header`都會帶上`cache-contro:max-age=0`,所以不會命中強緩存(參考:How do I stop Chrome sending Cache-control: max-age=0 when I hit enter?),但是通過鏈接點擊的地址會命中緩存。

chrome下查看所有的from cache文件:chrome://view-http-cache/


這是移除了 Entity Tag 的長時間緩存,在用戶沒有刷新頁面的情況下觸發。

具體怎麼配置,涉及 EntityTag 和 Expire Date 或者 Max Age 。詳情可以看這兩篇筆記,第一篇是緩存設置,第二篇是需要注意的 Entity Tag 的問題:

《High Performance Web Sites》之 Rule 3 讀書筆記

High Performance Web Sites Rule 13

======= 200 OK 還是 304 Not Modified 的分割線 =======

200 OK (from cache) 指的是瀏覽器都沒和伺服器確認,直接用了瀏覽器緩存。

304 Not Modified 比 200 OK (from cache) 慢,指的是瀏覽器還向伺服器確認了下 "If-Not-Modified",才用的緩存。

所以 Chrome 裡面,長時間緩存有時候顯示為 200 OK(from cache),有時候顯示為 304 Not Modified。前者是直接按回車訪問時發生,後者是按了 F5 刷新、或是 Entity Tag 沒有正確禁用的情況。@柳易寒@權一@陳肖恩

================回答結束的分割線===============

參考資料來自 stack overflow:httpwebrequest

拓展閱讀 :200 OK (from cache) 與 304 Not Modified


這個問題看起來為何如此詭異? 難道不是 http 頭域設置了緩存時間么? 始終 這話是指什麼呢? 強刷也是么? 沒聽說過呢...至少也會304吧.


通過大家的回答和我自己的實驗發現(Chrome上),對於阿里雲的雲存儲,加大Cache-Control的max-age是有效的,這點我之前也試過,但是像 @yuanyuanVivian說的,是在輸入URL按下回車時有效,直接刷新時圖片還是無法直接載入緩存,而且無法禁用阿里雲存儲Etag,但是事實上,還有一種方式可以讓瀏覽器直接使用200 OK (form cache)緩存,那就是在其它元素都載入完時通過js插入圖片或設置背景圖片。在jquery里就是$(window).load()的時候。

$(window).load(function() {
var bg="http://img.infinitynewtab.com/wallpaper/100.jpg";
setTimeout(function() {
$("#bgOut").css("background-image", "url("+bg+")");
},0);
});

其中setTimeout(xxx,0)是必須的,沒有這句還是會以304 Not Modified 的方式緩存

而用上之後:

另外在DOM載入時將setTimeout的時間設置大一點也是可以的,但是你無法判斷在不同的環境下這個時間是多少。

我寫了個頁面大家可以用Chrome瀏覽器來測試一下是不是這樣:Test

結果截圖:

即使用強制刷新,圖片也可以直接讀取緩存了。

PS.測試不充分,僅Windows Chrome 版本 41.0.2272.89 m


HTTP/1.1 Cache-Control的理解

試試cache-control,如果要緩存的話,不應該告知304先?


加大max-age 加大expires


Expires


header中打個過期時間即可實現。


推薦閱讀:

Chrome 有沒有可能超過 IE,成為全球市場佔有率最高的網頁瀏覽器?
360 極速瀏覽器和 Chrome 相比,劣勢在哪裡?
Chromebook 的使用體驗如何?
chrome瀏覽器出現問題,滑鼠點擊切換標籤頁變成關閉標籤頁?
Chrome 瀏覽器是怎麼辨別除網頁上字與詞之間的間隔的?

TAG:GoogleChrome | 前端開發 | 網頁瀏覽器 | 伺服器 | HTTP |