瀏覽器緩存機制淺解

瀏覽器的緩存機制:

  • 1: 瀏覽器會在第一次請求完服務器後獲得響應, 咱們能夠在服務器中設置這些相應,
    從而達到在之後的請求中儘可能減小甚至不從服務器獲取資源的目的。
  • 2: 瀏覽器緩存中涉及到的頭信息
    瀏覽器的緩存是依靠請求和響應中的的頭信息來控制緩存的。html

    1: expires
    最簡單的過時緩存方式, 在第一次請求時返回的頭信息中設置一個exires時間,在後面的請求的時候, 請求會帶着這個expires時間, 假如在這個expires時間內,瀏覽器不會向服務器發送請求, 而是直接從本地緩存副本中讀取數據數據庫

    2:Cache-Control
    他有一些不一樣的值對應不一樣的緩存策略,這裏我查到一個,參考一下初探 HTTP 1.1 Cache 機制
    這裏要說明的是Cache-Control的設置會覆蓋expires的設置, 並且常與Last-Modified和Etag配合使用segmentfault

    3:Last-Modified/Last-Modified-Since
    在使用這個緩存策略的時候, 瀏覽器每次都會向服務器發送請求, 但服務器能夠根據Last-Modified-Since向瀏覽器返回200或者304, 若是返回304, 就是告訴瀏覽器讓它直接從客戶端電腦的緩存中讀取副本吧, 不然就會把請求的資源以200的方式返回給瀏覽器。瀏覽器

    這裏也要說明一下, Last-Modified是瀏覽器第一次向服務器請求以後, 服務器響應中設置的(即代碼中設定), 而Last-Modified-Since則是瀏覽器每次向服務器請求的時候帶着的Last-Modified的值, 好比第一次請求後響應的Last-Modified的值是A, 那麼在後面每次請求的時候的Last-Modified-Since的值就是A, 直到服務器從新設置了Last-Modified的值緩存

    4: Etag/If-None-Match
    ETag是一種與Last-Modified/Last-Modified-Since相似的控制方式。用戶在第一次請求的時候服務器能夠本身生成或由用戶生成, 而後響應給瀏覽器, 那麼在之後的請求中,會帶着If-None-Match, 它的值就是以前生成的Etag。 在服務器中對比服務器上的Etag與If-None-Match, 假如相同, 則返回304, 不然請求並返回服務器資源。服務器

    這裏有一個問題, 如何生成Etag, 尤爲是動態頁面中, 假如資源發生變化, Etag要從新生成。 我這裏想到一種方式, 請求到服務器後, 仍是要進行必要的代碼運行, 在代碼中, 拿到相關的變量生成一個Etag值, 對比傳遞上來的If-None-Match, 再斷定返回的狀態值。(原諒個人經驗有限, 這只是一種方式,若是各位有新的思路, 歡迎加入討論)。函數

    5: Cache-Control/Expires的優先級要高於Last-Modified/Etag,Cache-Control/Expires是控制瀏覽器是否向服務器拉資源, Last-Modified/Etag是服務器控制是否返回一個完整的請求資源,仍是返回一個304, 假如本地連請求都不會拉, 那Last-Modified/Etag就無從談起了.post

實現:

下面使用PHP分別實現以上幾種緩存方式, 通常服務器上的靜態文件都會默認使用Last-Modified/Last-Modified-Since,
因此不少的靜態文件在二,三,四。。。次刷新的時候都是304狀態(Not Modified).

另外下面的過時時間都是格林威治時間才行,可使用gmdate函數獲取。
/*
      Last-Modified/Last-Modified-Since
      我想這裏若是用一些數據保存方式,如memcache或數據庫, 把某個文件的修改時間保存起來, 若是文件修改了, 則更新這個數據, 而後每次刷新這裏的這個頁面的時候,先讀取修改時間,  若是傳遞的$lastModifiedSince修改時間不符, 則從新讀取, 不然返回304
      測試的結果是在在緩存時間內返回304
     */

     $cacheTime = 60;
     $lastModifiedSince = strtotime(@$_SERVER['HTTP_IF_MODIFIED_SINCE']);
     if($lastModifiedSince + $cacheTime > time())
     {
       header("HTTP/1.1 304"); 
       die('use cache');
     }
     header('Last-Modified: '.gmdate('D d M Y H:i:s', time()).' GMT');
     echo time();


/*
    Etag/If-None-Match
    測試的結果是在服務器上的資源未發生變化時返回的304
*/

    $user_id = 1;
    $etag = md5($user_id);


    $matchEtag = @$_SERVER['HTTP_IF_NONE_MATCH'];

    if($matchEtag == $etag)
    {
        header("HTTP/1.1 304");
        die('use cache');
    }

    header('Etag: '.$etag);
    echo time();

問題:

在測試expires和Cache-Control的max-age的時候, 本地緩存無效, 每次仍是發起請求, 並無讀取緩存, 不知爲什麼?
請看鏈接測試

PS: 文章中可能有錯誤的地方, 若是發現, 請及時指出code

相關文章
相關標籤/搜索