瀏覽器的緩存策略,會暫時將瀏覽過的文件緩存在本地磁盤,當(dāng)用戶重復(fù)請求頁面時,告知客戶端頁面并沒有發(fā)生改變,可以調(diào)用緩存,那么如何知道客戶端是否有頁面緩存呢?從 HTTP 協(xié)議層面來說,瀏覽器發(fā)送請求時會先發(fā)送如下:
- HTTP 頭:
- Connection Keep-Alive
- Date Sun, 06 May 2012 18:00:36 GMT
- Last-Modified Sun, 06 May 2012 17:31:02 GMT
- Etag ec1f629013925ab0fa4389ba926e8c06
- Keep-Alive timeout=15, max=299
- Server Apache/2.2.16 (Unix) DAV/2
- Vary Accept-Encoding
請注意其中的這兩行,描述了頁面的緩存信息:
Last-Modified Sun, 06 May 2012 17:31:02 GMT
Etag ec1f629013925ab0fa4389ba926e8c06這個情況下,如果服務(wù)器響應(yīng) 304 狀態(tài)碼,瀏覽器會自覺地從緩存中讀取數(shù)據(jù),如果響應(yīng) 200 狀態(tài)碼,不管有沒有客戶端緩存,照樣從服務(wù)端讀取.
按照這個理論支撐,比如站長軍團大部分查詢結(jié)果都是 ajax 異步獲取的,二次訪問就都可以通過這種方式進行緩存改造,只要客戶端有緩存,就向客戶端發(fā)送一個 304 響應(yīng)狀態(tài)碼,然后退出程序執(zhí)行.
瀏覽器發(fā)出的請求中包含 If-Modified-Since 和 If-None-Match 兩個參數(shù):
If-Modified-Since 表示詢問數(shù)據(jù)的最后修改時間是否是某個時間值。然后服務(wù)器會檢查數(shù)據(jù)的最后修改時間,如果是該時間則返回 304 狀態(tài)碼,客戶端接收到該狀態(tài)碼后直接從本地讀取緩存。這種情況有一個前置條件,即本地必須存在緩存資源,瀏覽器才會發(fā)送 If-Modified-Since 參數(shù),并且值為上一次服務(wù)器返回的 Last-Modified 值。
If-None-Match 類似,它由服務(wù)器返回的 Etag 值生成,僅僅用于服務(wù)器檢查數(shù)據(jù)的修改時間,可以是任意值。考慮到 If-Modified-Since 結(jié)合 Last-Modified 的方法并不被所有服務(wù)器支持,這里就只考慮使用 etag 的實現(xiàn)。
PHP 中通過 $_SERVER['HTTP_IF_NONE_MATCH'] 可以判斷文件是否被瀏覽器緩存,代碼片段如下:
- //使用 etag 標(biāo)記控制緩存
- $etag = md5(date('Ymd'));
- if ($_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
- header('Etag:' . $etag, true, 304);
- exit();//開源代碼Vevb.com
- } else {
- header('Etag:' . $etag);
- }
這里我使用當(dāng)日日期來生成 etag,這樣可以保證緩存最多生效一天時間,這個參數(shù)可以根據(jù)需要修改.
補充說明:即便是 304 響應(yīng),實際上還是會請求服務(wù)端,因為需要建立連接來判斷是否需要傳輸數(shù)據(jù),304 緩存節(jié)約的是靜態(tài)資源傳輸?shù)拈_銷.
另一種緩存是 200 響應(yīng)時的緩存,不建立連接但請求會響應(yīng) 200 狀態(tài)碼,并從本地直接讀取緩存.
新聞熱點
疑難解答