咱們都知道對頁面進行緩存可以有利於減小請求發送,從而達到對頁面的優化。不過在我前端工做的生涯中一直覺得前端就是寫寫頁面,寫寫交互,就已經很了不得,這種沒有志向的想法發致使我往後的工做一直處於瓶頸。作人嘛總要有夢想嘛,否則跟一條鹹魚有什麼區別。最近我一直在關於前端優化的問題,原來對頁面進行有效緩存對於響應速度會大大提升。我也是綜合本身看到的幾篇文章,談談見解,權當是一次學習筆記吧,有什麼不對的請多多包涵。廢話很少說,開始正題。php
緩存機制
html
緩存分爲服務端側(server side,好比 Nginx、Apache)和客戶端側(client side,好比 web browser)。
前端
服務端緩存又分爲 代理服務器緩存 和 反向代理服務器緩存(也叫網關緩存,好比 Nginx反向代理、Squid等),其實普遍使用的 CDN 也是一種服務端緩存,目的都是讓用戶的請求走」捷徑「,而且都是緩存圖片、文件等靜態資源。
瀏覽器緩存控制機制有兩種:HTML Meta標籤 vs. HTTP頭信息
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代碼的做用是告訴瀏覽器當前頁面不被緩存,每次訪問都須要去服務器拉取。使用上很簡單,但只有部分瀏覽器能夠支持,並且全部緩存代理服務器都不支持,由於代理不解析HTML內容自己。
web
一、服務端緩存相關api
什麼是Etag?什麼是Last-Modified?等等這些,都是什麼鬼,之前我一看到都是直接懵逼。瀏覽器
首先咱們要先根據http請求頭以及響應頭 先看一些跟緩存相關的報文頭cache-control, if-none-match, if-modified-since, Etag,expires, last-modified,
request header緩存相關:
cache-control:
其緩存指令對於前段經常使用的有以下no-cache、no-store、max-age這幾個值;分別來講一下
no-cache:
表面意爲「數據內容不被緩存」,而實際數據是被緩存到本地的,只是每次請求時候直接繞過緩存這一環節直接向服務器請求最新資源,因爲瀏覽器解釋不同,
例如ie中咱們設置了no-cache以後,請求雖然不會直接使用緩存,可是還會用緩存數據與服務器數據進行一致性檢測(也就是說仍是有概率會用到緩存的),
firefox中則徹底無視no-cache存在,詳細解釋見no-store;
no-store:
指示緩存不存儲這次請求的響應部分。與no-cache比較來講,一個是不用緩存,一個是不存儲緩存;按理來講這個設置更加粗暴直接禁用緩存,
可是具體實現起來 瀏覽器之間差別卻特別大,通常不會直接用該字段進行設置,不過no-store是爲了防止緩存被惡意修改存儲路徑致使信息被泄露而設置的,
畢竟有它的用處,在firefox中實現緩存是經過文件另存爲將緩存副本保存到本地,直接利用no-cache對其是無效的,若是加上no-store設置的話 則能夠起到與no-cache同樣的效果;
即:cache-control:no-cache,no-store;能夠確保在支持http1.1版本中各大瀏覽器回車後退刷新無緩存;
再加上Pragma: no-cache設置兼容版本1.0便可(不過爲了防止一致性檢測時候的萬一咱們仍是最好加上一致性檢測的內容,以下所示幾種方式);
max-age:
例如Cache-control: max-age=3;表示這次請求成功後3秒以內發送一樣請求不會去服務器從新請求,而是使用本地緩存;一樣咱們若是設置max-age=0表示當即拋棄緩存直接發送請求到服務器
一致性檢測分爲兩種方式:1.檢測日期是否過時,檢測資源是否更新;
if-none-match:
該字段與響應中的eTag一塊兒使用,表示檢查實體是否有更新改變;客戶端第一次發送請求時候響應報文會包含字段Etag,表示資源狀態,當資源改變後該值也會改變(客戶端沒必要關心該值怎麼生成)
而後緩存保存下該字段,第二次已經有該緩存時候在瀏覽本地緩存時候會將該值賦給if-none-match字段發送給服務器,服務器將發送的值與當前的狀態進行對比,
若是值同樣的話則答覆304去使用緩存數據,若是值改變了則發送最新數據給客戶端替代現有緩存數據,而且返回狀態200;
if-modified-since:
該字段與last-modified配合使用,跟上述原理差很少,都是響應端先返回一個last-modified時間字段,再次請求時候 request頭部會將緩存中的last-modified字段拿出來賦給if-modified-since,
發送給服務器,服務器去判斷時間是否過時,如未過時則返回304,告訴客戶使用緩存數據,若是過時則從新返回一個last-modified而且返回200;
repsonse header緩存相關:
Etag:
剛纔也說過 是跟if-none-match配合去使用,它根據實體內容生成的一段hash字符串(相似於MD5或者SHA1以後的結果),能夠標識資源的狀態。 當資源發送改變時,ETag也隨之發生變化。
使用Etag主要是爲了解決根據時間沒法解決的問題:好比文件修改頻繁(秒以內修改),致使根據時間沒法判斷是否更新;以及修改時間變了,可是內容沒變(咱們應該認爲該文件是沒變的)
expires:
表示緩存過時時間例如:expires:Mon Dec 30 2011 11:01:19 GMT,跟cache-control中的max-age做用同樣,不過在遇見max-age以後,該值會被覆蓋從而被max-age替代;
last-modified:
表示文件最後修改時間;
另外響應端的報文頭也有對cache-content的規定,與request大致相同,另有未說起的 歡迎你們補充
緩存
使用緩存:服務器
默認狀況下,瀏覽器都會使用緩存數據,網絡
在f5刷新狀況下 瀏覽器會發送一致性驗證去服務器驗證是否使用緩存,而瀏覽器直接回車則表示直接應用緩存不須要去服務器驗證;因此咱們就按照f5刷新去解釋實現使用緩存:dom
通常來講前端默認是使用緩存的,默認狀況下服務器端以及前端都會使用緩存數據,或者是根據etag或者是根據max-age或者是根據expires根據服務器不一樣去不一樣實現;
實際中大部分不須要咱們手動去實現,而有些咱們不肯定是否使用緩存的狀況下咱們能夠手動加以干涉強制使用緩存數據:
例如某個靜態文件包括html或者圖片咱們須要使用緩存來提升處理速度,
方法一:
在服務器進行配置其max-age或者expires使其設置一個過時值爲當前一年以後。這樣每次進行檢驗時候都會使用緩存中文件.例如在.htaccess中
<IfModule mod_headers.c>
<FilesMatch ".(gif|jpg|jpeg|png|ico)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
方法二:
前端設置if-modified-since去設置一個上次修改時間大於當前日期,
方法三:
服務器端根據etag去判斷是否匹配來根據實際業務來使用緩存;
後面兩個方法屬於弱緩存數據頭,須要浪費http鏈接,因此建議使用第一種方式;
禁用緩存:
方法一:
能夠在meta標籤標明<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
方法二:
也能夠動態去setRequestHeader,強制不用緩存設置組合以下:
cache-control='no-cache,no-store'
pragma='no-cache'
if-modified-since=0;
方法三:
請求端設置if-modified-since爲已通過期的某個時間,能夠是幾年前或者幾十年前。
方法四:
服務端設置Expires爲過時某個時間,例如php中header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
實際開發中若是須要一致性檢測則儘可能去配合Etag以及last-Modified去進行比較而後返回使用緩存仍是新數據;這個有點偏服務器端了,再也不贅述
方法五:
url後面加隨機數或者時間戳url += 「&random=」 + Math.random()這個方法js以及php常常用,原理就是每一個請求的url都不同這樣一來緩存中找不到對應數據,就自動去服務器尋找最新資源;
二、瀏覽器緩存相關
瀏覽器緩存是瀏覽器端保存數據用於快速讀取或避免重複資源請求的優化機制,有效的緩存使用能夠避免重複的網絡請求和瀏覽器快速地讀取本地數據,總體上加速網頁展現給用戶。瀏覽器端緩存的機制種類較多,打開瀏覽器的調試模式->resources左側就有瀏覽器的8種緩存機制。
上述的緩存機制js都有相關的api進行操做,請自行查詢。上面其實都是我粘貼複製的,由於這幾篇文章讓當時的我有種醍醐灌頂的感受。詳情能夠參考以下連接