瀏覽器緩存知識概括

瀏覽器緩存(Browser Catching)是爲了節約網絡的資源加速瀏覽,瀏覽器在用戶磁盤上對最近請求過的文檔進行存儲,當訪問者再次請求這個頁面時,瀏覽器就能夠從本地磁盤顯示文檔,這樣就能夠加速頁面的閱覽。 —-摘自《百度百科》css

瀏覽器緩存是提高網頁性能的一大利器,可是,也是一把雙刃劍。利用的好網頁的性能會有大幅度提高,服務器的壓力也會減少。利用的很差,也會遇到不少的問題。本文結合瀏覽器緩存的知識,結合真實案例進行分析,但願對讀者有所幫助。node

瀏覽器緩存分類瀏覽器

瀏覽器緩存分爲強緩存和協商緩存,瀏覽器加載一個頁面的簡單流程以下:緩存

  1. 瀏覽器先根據這個資源的http頭信息來判斷是否命中強緩存。若是命中則直接加在緩存中的資源,並不會將請求發送到服務器。服務器

  2. 若是未命中強緩存,則瀏覽器會將資源加載請求發送到服務器。服務器來判斷瀏覽器本地緩存是否失效。若可使用,則服務器並不會返回資源信息,瀏覽器繼續從緩存加載資源。網絡

  3. 若是未命中協商緩存,則服務器會將完整的資源返回給瀏覽器,瀏覽器加載新資源,並更新緩存。

強緩存ide

命中強緩存時,瀏覽器並不會將請求發送給服務器。在Chrome的開發者工具中看到http的返回碼是200,可是在Size列會顯示爲(from cache)。函數

瀏覽器緩存知識概括
強緩存是利用http的返回頭中的Expires或者Cache-Control兩個字段來控制的,用來表示資源的緩存時間。工具


Expires
性能

該字段會返回一個時間,好比Expires:Thu,31 Dec 2037 23:59:59 GMT。這個時間表明着這個資源的失效時間,也就是說在2037年12月31日23點59分59秒以前都是有效的,即命中緩存。這種方式有一個明顯的缺點,因爲失效時間是一個絕對時間,因此當客戶端本地時間被修改之後,服務器與客戶端時間誤差變大之後,就會致使緩存混亂。因而發展出了Cache-Control。

Cache-Control

Cache-Control是一個相對時間,例如Cache-Control:3600,表明着資源的有效期是3600秒。因爲是相對時間,而且都是與客戶端時間比較,因此服務器與客戶端時間誤差也不會致使問題。

Cache-Control與Expires能夠在服務端配置同時啓用或者啓用任意一個,同時啓用的時候Cache-Control優先級高。

協商緩存

若未命中強緩存,則瀏覽器會將請求發送至服務器。服務器根據http頭信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match來判斷是否命中協商緩存。若是命中,則http返回碼爲304,瀏覽器從緩存中加載資源。

Last-Modify/If-Modify-Since

瀏覽器第一次請求一個資源的時候,服務器返回的header中會加上Last-Modify,Last-modify是一個時間標識該資源的最後修改時間,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

瀏覽器緩存知識概括
當瀏覽器再次請求該資源時,上送的請求頭中會包含If-Modify-Since,該值爲緩存以前返回的Last-Modify。服務器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存。

瀏覽器緩存知識概括

若是命中緩存,則返回http304,而且不會返回資源內容,而且不會返回Last-Modify。因爲對比的服務端時間,因此客戶端與服務端時間差距不會致使問題。可是有時候經過最後修改時間來判斷資源是否修改仍是不太準確(資源變化了最後修改時間也能夠一致)。因而出現了ETag/If-None-Match。

ETag/If-None-Match

與Last-Modify/If-Modify-Since不一樣的是,Etag/If-None-Match返回的是一個校驗碼(ETag: entity tag)。ETag能夠保證每個資源是惟一的,資源變化都會致使ETag變化*。服務器根據瀏覽器上送的If-None-Match值來判斷是否命中緩存。

瀏覽器緩存知識概括

* ETag擴展說明

咱們對ETag寄予厚望,但願它對於每個url生成惟一的值,資源變化時ETag也發生變化。神祕的Etag是如何生成的呢?以Apache爲例,ETag生成靠如下幾種因子

  1. 文件的i-node編號,此i-node非彼iNode。是Linux/Unix用來識別文件的編號。是的,識別文件用的不是文件名。使用命令’ls –I’能夠看到。

  2. 文件最後修改時間

  3. 文件大小

  4. 生成Etag的時候,可使用其中一種或幾種因子,使用抗碰撞散列函數來生成。因此,理論上ETag也是會重複的,只是機率小到能夠忽略。

生產問題分析

背景:某次投產,某系統投產後因爲強緩存設置時間不恰當致使變動的功能沒有體現。後來經過變動文件路徑強行解決問題。

變動上下文根,致使URL變化必定能夠解決問題。但咱們不可能每一次都這麼作;還有,在瀏覽器端關閉緩存、或者清除緩存後再繼續瀏覽、同時使用Ctrl+F5刷新,也能夠解決問題,可是咱們也不可能讓每個客戶在投產後都作一次這個操做。

那咱們怎麼辦呢?從問題緣由來看,是將常常變化的資源緩存時間設置的過長致使的。理論上來說,只要正確劃分常常變化資源與不常常變化資源就能夠解決問題。可是誰也不能保證不常常變化的資源就必定不會變化。

萬一不常常變化的資源變動了怎麼辦呢?在資源請求的URL中增長一個參數,好比:css/main.css?v=20160105。這個參數是一個版本號,客戶化在js代碼中,每一次投產的時候變動一下,當這個參數變化的時候,強緩存都會失效並從新加載。這樣一來,即便是不常變化的資源,投產之後也須要從新加載。這樣就完美的解決了問題。

本文參考數篇技術博客、百度百科、維基百科、Apache官方說明以及本身的理解完成,若有不正確的地方歡迎斧正。

相關文章
相關標籤/搜索