在咱們開發網站的時候每每對網站的性能有極高的需求,固然,外包的除外哈.我見過的外包對效率要求特別高.對代碼質量以及性能要求都不是很高.因此這裏就不說明太多.高性能就意味着要使用各式各樣的緩存,後臺redis/memcached緩存等,前臺就是瀏覽器緩存.什麼是瀏覽器緩存.簡單來講,就是瀏覽器繼續使用從服務器上的內容,而不去使用服務器上的內容.那如何使用呢,在使用以前,咱們先來說講瀏覽器刷新機制.php
常見的瀏覽器刷新有以下幾個,Ctrl+F5,Ctrl+R,F5,還有個就是轉到,前進.不要認爲前進就不是刷新了.其實這個是錯誤的.下面咱們來說講這幾個區別.html
Ctrl + F5: 這個在開發過程當中,常用,爲何說呢,Ctrl+F5爲強制刷新,讓瀏覽器不遵照緩存協議,強制的所有從新在服務器上去請求.全部資源都所有從新的去請求. Ctrl + R|F5: 讓瀏覽器遵照緩存協議,例如last-modified,etag等這些.若是這是服務端返回的是304就認爲沒有修改,就會直接調用以前的內容.具體的等下面在講解.用戶最多的操做 前進->: 還有相似於這種操做,就是輸入瀏覽器直接回車.瀏覽器會將代碼Expires的而且沒有過時的所有使用,以最少的請求去請求瀏覽器.就不用擔憂這種也是強制刷新了.
下面咱們就來說講一些常見的用了瀏覽器緩存的例子.nginx
在咱們瀏覽網站的時候,常常能看到這個頭部信息,這個頭部信息是用來記錄最後一次的修改時間.若是網站響應的頭部信息有這個,那麼下次訪問的時候,瀏覽器會帶上一個這樣的標識web
If-Modified-Since:時間
而後服務端能夠根據這個來判斷是否是應該能夠直接使用緩存.固然,通常動態的網頁是不多用這種的,由於不存在傳統意義上的最後的修改時間.通常會用於靜態網站長時間不修改文件的內容等.咱們來作一個簡單示例.redis
<?php // 判斷是否含有這個最後一次修改時間,若是有,就強制使用304,讓瀏覽器使用緩存.並終止程序. if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { header('HTTP/1.1 304 Not Modified'); exit; } // 添加最後一次的修改時間 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); echo date('Y-m-d H:i:s');
這裏的作法雖然並不合理,沒有判斷時間,只要存在就使用緩存.這僅僅是爲了看下效果,開發程序時應該有更好的作法.讓咱們來看看效果.咱們把這個命令成index.php,放在localhost執行的地址,讓咱們來看看
第一次訪問,瀏覽器獲得的last-modified這個響應頭,咱們來看看請求頭和響應頭瀏覽器
--Response Headers-- Connection:keep-alive Content-Encoding:gzip Content-Type:text/html; charset=UTF-8 Date:Fri, 11 May 2018 02:19:51 GMT Last-Modified:Fri, 11 May 2018 01:37:15 GMT Server:nginx/1.9.15 (Ubuntu) Transfer-Encoding:chunked --Request Headers-- Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.9 Cache-Control:no-cache Connection:keep-alive Host:localhost Pragma:no-cache Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
從上面能夠看出,對於第一次訪問的網站,瀏覽器並無緩存.而後當咱們再次使用了F5過來,在來看看
這裏咱們的程序代碼是直接退出程序,沒有任何輸出,那爲何還有這個輸出,這個正式由於瀏覽器讀取本身的緩存.讓咱們看看響應頭.緩存
--Response Headers-- Connection:keep-alive Date:Fri, 11 May 2018 02:26:57 GMT Server:nginx/1.9.15 (Ubuntu)
這裏僅有簡單的幾行,指明瞭web服務器和系統,再來看看請求頭服務器
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.9 Cache-Control:max-age=0 Connection:keep-alive Host:localhost If-Modified-Since:Fri, 11 May 2018 01:37:15 GMT Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
添加了一個If-Modified-Since,讓咱們來判斷有效期,這個就是讓咱們來判斷是否使用瀏覽器緩存的一個標識.因此這個就讓咱們的瀏覽器強制使用了緩存.app
這個頭又是用來幹嗎的,這個又是跟瀏覽器協商的另外一種方法,它於前面的last-modified很是類似,可是它沒有用文件的最後修改時間,而是用一段編碼倆標記內容,這個編碼並無強制要求,可是咱們一般用一個文件內容的md5來做爲Etag.一個原則就是,若是一個內容的Etag沒有變化,那麼這個內容也必定沒有更新.讓咱們來弄一個簡單的示例.memcached
<?php $date = date('Y-m-d'); // 咱們這裏用當前的日期來代替文件md5 // 判斷請求頭中是否存在if-none-match,若是存在就去判斷md5,若是值同樣,就返回304 if (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) && $_SERVER['HTTP_IF_NONE_MATCH'] == 'W/"' . md5($date) . '"') { header('HTTP/1.1 304 Not Modified'); exit; // 退出 } // 添加請求頭. header('Etag: "' . md5($date) . '"'); echo date('Y-m-d H:i:s');
這裏咱們的程序代碼是跟咱們用last-modified是同樣的.對於咱們來講,也是不合理的,只是用來當成示例而已方便理解.讓咱們來看看執行效果.
第一次都是強制請求,若是前面的沒有處理,就先Ctrl+F5,這裏就先說明這個.具體的部署仍是跟上一步的步驟同樣.讓咱們看看響應頭
--Response Headers-- Connection:keep-alive Content-Encoding:gzip Content-Type:text/html; charset=UTF-8 Date:Fri, 11 May 2018 02:45:07 GMT Etag:W/"64ddf4c4fbf56a689c963872a8325370" Server:nginx/1.9.15 (Ubuntu) Transfer-Encoding:chunked
在響應頭裏面增長一項,Etag,固然這個是咱們的程序輸出的.用程序控制的.咱們來看看F5事後的結果
咱們看見響應頭中多了一個If-None-Match這個跟咱們上一個請求的Etag值是同樣的.
--Request Headers-- Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.9 Cache-Control:max-age=0 Connection:keep-alive Host:localhost If-None-Match:W/"64ddf4c4fbf56a689c963872a8325370" Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
這個對於咱們來講,在程序中咱們也是直接中止了,而且報出304的狀態碼,可是瀏覽器仍是做出反映了,將之前的值拿過來用了.這個就是咱們的Etag
既然這兩個都是用來做用瀏覽器緩存的.那誰的優先級高呢,其實沒有優化級,根據咱們服務的處理來的.咱們若是優先處理Etag那就Etag值高,優先處理Last-Modified就Last-Modified高.
上面兩種方式已經說明了,可是咱們仍是會常常看到,在咱們退出瀏覽器事後,再次訪問這個網站的時候,仍是讀取的緩存.顯然,咱們上面兩種都不行的.不信你試試.這裏咱們就介紹另一種,Expires,咱們先來例子
<?php $stream = file_get_contents('./etag-1.png'); $seconds_to_cache = 3600; $ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT"; header('Content-Type: image/png'); header("Expires: $ts"); echo $stream;
當咱們第一次訪問的時候,用localhost訪問時,會獲得一張圖片.而且緩存1個小時,而後咱們退出瀏覽器.並修改代碼
<?php exit('111111'); $stream = file_get_contents('./etag-1.png'); $seconds_to_cache = 3600; $ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT"; header('Content-Type: image/png'); header("Expires: $ts"); echo $stream;
而後在訪問時,依然會獲得咱們的圖片,並無獲得咱們所謂的6個1.這個圖片已經被瀏覽器緩存下來了.Expires是絕對時間.同理還有一個相對的,Cache-Control這裏我就不演示,能夠本身根據代碼來做出演示便可.
咱們根據以上的得出以下結果
Last-Modified -> If-Modified-Since // 瀏覽器緩存於當前會話 Etags -> If-Modified-Since // 瀏覽器緩存當前會話 Expires // 關閉後也有效 Cache-Control // 關閉後也有效
咱們能夠根據不一樣的場景應用不一樣的緩存機制了.