瀏覽器從輸入到輸出的過程與原理二之緩存

1. 瀏覽器緩存

瀏覽器緩存的知識是前端工程師必需要掌握的,由於這些知識直接影響到你的頁面的用戶體驗,影響到你的頁面的加載策略。接下來將要詳細的講述瀏覽器緩存的概念和原理,緩存的知識除了和瀏覽器有關,還涉及到HTTP協議。前端

1.1 概念

瀏覽器緩存(Browser Caching)是爲了節約網絡的資源加速瀏覽,瀏覽器在用戶磁盤上對最近請求過的文檔進行存儲,當訪問者再次請求這個頁面時,瀏覽器就能夠從本地磁盤顯示文檔,這樣就能夠加速頁面的閱覽。瀏覽器緩存主要有兩類:緩存協商和強緩存。web

1.2 請求流程圖

image

上圖是瀏覽器第一次請求時發生過流程,瀏覽器顯然不存在任何緩存數據,瀏覽器跳過校驗緩存這一步,直接進入下一個流程,向網絡發起請求,也就是上圖中的[ 向web服務器發起請求 ]。算法

這個過程包含不少內容,將在後續的內容敘述。瀏覽器

image

從上面的請求流程圖能夠知道,瀏覽器緩存包含兩種類型,即強緩存(也叫本地緩存)和協商緩存。緩存

強緩存

強緩存是與(cache-control和expires信息)有關的緩存。服務器

cache-control

Cache-Control 是最重要的規則。這個字段用於指定全部緩存機制在整個請求/響應鏈中必須服從的指令。這些指令指定用於阻止緩存對請求或響應形成不利干擾的行爲。這些指令一般覆蓋默認緩存算法。緩存指令是單向的,即請求中存在一個指令並不意味着響應中將存在同一個指令。網絡

cache-control 定義是:Cache-Control = 「Cache-Control」 「:」 cache-directive。前端工程師

網頁的緩存是由HTTP消息頭中的「Cache-control」來控制的,常見的取值有private、no-cache、max-age、must-revalidate等,默認爲private。測試

表 1. 經常使用 cache-directive 值編碼

Cache-directive

說明

public

全部內容都將被緩存(客戶端和代理服務器均可緩存)

private

內容只緩存到私有緩存中(僅客戶端能夠緩存,代理服務器不可緩存)

no-cache

必須先與服務器確認返回的響應是否被更改,而後才能使用該響應來知足後續對同一個網址的請求。所以,若是存在合適的驗證令牌 (ETag),no-cache 會發起往返通訊來驗證緩存的響應,若是資源未被更改,能夠避免下載。

no-store

全部內容都不會被緩存到緩存或 Internet 臨時文件中

must-revalidation/proxy-revalidation

若是緩存的內容失效,請求必須發送到服務器/代理以進行從新驗證

max-age=xxx (xxx is numeric)

緩存的內容將在 xxx 秒後失效, 這個選項只在HTTP 1.1可用, 並若是和Last-Modified一塊兒使用時, 優先級較高

表 2 代表在不一樣的情形下,瀏覽器是將請求從新發送到服務器仍是使用緩存的內容。

表 2. 對 cache-directive 值的瀏覽器響應

Cache-directive

打開一個新的瀏覽器窗口

在原窗口中單擊 Enter 按鈕

刷新

單擊 Back 按鈕

public

瀏覽器呈現來自緩存的頁面

瀏覽器呈現來自緩存的頁面

瀏覽器從新發送請求到服務器

瀏覽器呈現來自緩存的頁面

private

瀏覽器從新發送請求到服務器

第一次,瀏覽器從新發送請求到服務器;此後,瀏覽器呈現來自緩存的頁面

瀏覽器從新發送請求到服務器

瀏覽器呈現來自緩存的頁面

no-cache/no-store

瀏覽器從新發送請求到服務器

瀏覽器從新發送請求到服務器

瀏覽器從新發送請求到服務器

瀏覽器從新發送請求到服務器

must-revalidation/proxy-revalidation

瀏覽器從新發送請求到服務器

第一次,瀏覽器從新發送請求到服務器;此後,瀏覽器呈現來自緩存的頁面

瀏覽器從新發送請求到服務器

瀏覽器呈現來自緩存的頁面

max-age=xxx (xxx is numeric)

在 xxx 秒後,瀏覽器從新發送請求到服務器

在 xxx 秒後,瀏覽器從新發送請求到服務器

瀏覽器從新發送請求到服務器

在 xxx 秒後,瀏覽器從新發送請求到服務器

Cache-Control是關於瀏覽器緩存的最重要的設置,由於它覆蓋其餘設置,好比 Expires 和 Last-Modified。另外,因爲瀏覽器的行爲基本相同,這個屬性是處理跨瀏覽器緩存問題的最有效的方法。

Expires

Expires 頭部字段提供一個日期和時間,響應在該日期和時間後被認爲失效。失效的緩存條目一般不會被緩存(不管是代理緩存仍是用戶代理緩存)返回,除非首先經過原始服務器(或者擁有該實體的最新副本的中介緩存)驗證。(注意:cache-control max-age 和 s-maxage 將覆蓋 Expires 頭部。)

Expires 字段接收如下格式的值:「Expires: Sun, 08 Nov 2009 03:37:26 GMT」。若是查看內容時的日期在給定的日期以前,則認爲該內容沒有失效並從緩存中提取出來。反之,則認爲該內容失效,緩存將採起一些措施。

不一樣操做下不一樣瀏覽器的響應。具體相關內容參見百度百科詞條

協商緩存

協商緩存是與Last-Modified和Etag相關的緩存。

Last-Modified

在瀏覽器第一次請求某一個URL時,服務器端的返回狀態會是200,內容是客戶端請求的資源,同時有一個Last-Modified的屬性標記此文件在服務器端最後被修改的時間。

Last-Modified格式相似這樣:

Last-Modified : Fri , 12 May 2006 18:53:33 GMT

客戶端第二次請求此URL時,根據HTTP協議的規定,瀏覽器會向服務器傳送If-Modified-Since報頭,詢問該時間以後文件是否有被修改過:

If-Modified-Since : Fri , 12 May 2006 18:53:33 GMT

若是服務器端的資源沒有變化,則自動返回 HTTP 304(Not Changed.)狀態碼,內容爲空,這樣就節省了傳輸數據量。當服務器端代碼發生改變或者重啓服務器時,則從新發出資源,返回和第一次請求時相似。從而保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端可以獲得最新的資源。

Etag的概念

HTTP協議規格說明定義ETag爲「被請求變量的實體值」。另外一種說法是,ETag是一個能夠與Web資源關聯的記號(token)。典型的Web資源能夠是一個Web頁,但也多是JSON或XML文檔。服務器單獨負責判斷記號是什麼及其含義,並在HTTP響應頭中將其傳送到客戶端,如下是服務器端返回的格式:ETag:"50b1c1d4f775c61:df3"客戶端的查詢更新格式是這樣的:If-None-Match : W / "50b1c1d4f775c61:df3"若是ETag沒改變,則返回狀態304而後不返回,這也和Last-Modified同樣。測試Etag主要在斷點下載時比較有用。

客戶端請求一個頁面(A)。 服務器返回頁面A,並在給A加上一個ETag。 客戶端展示該頁面,並將頁面連同ETag一塊兒緩存。 客戶再次請求頁面A,並將上次請求時服務器返回的ETag一塊兒傳遞給服務器。 服務器檢查該ETag,並判斷出該頁面自上次客戶端請求以後還未被修改,直接返回響應304(未修改——Not Modified)和一個空的響應體。

Etag的優點

一、有些URL是多語言的網頁,相同的URL會返回不一樣的東東。還有不一樣的Session有不一樣的Cookie也就有不一樣的內容。這種狀況下若是過 Proxy,Proxy就沒法區分致使串門,只能簡單的取消cache功能。Etag解決了這個問題,由於它能區分相同URL不一樣的對象。

二、老的HTTP標準裏有個Last-Modified+If-Modified-Since代表URL對象是否改變。Etag也具備這種功能,由於對象改變也形成Etag改變,而且它的控制更加準確。Etag有兩種用法 If-Match/If-None-Match,就是若是服務器的對象和客戶端的對象ID(不)匹配才執行。這裏的If-Match/If-None- Match都能一次提交多個Etag。If-Match能夠在Etag未改變時斷線重傳。If-None-Match能夠刷新對象(在有新的Etag時返回)。

三、Etag中有種Weak Tag,值爲 W/"xxxxx"。他聲明Tag是弱匹配的,只能作模糊匹配,在差別達到必定閾值時才起做用。

四、Etag對於cache CGI頁面頗有用。特別是論壇,論壇有辦法爲每一個帖子頁面生成惟一的Etag,在帖子未改變時,查看話題屬性比較Etag就能避免刷新帖子,減小CGI操做和網絡傳輸。好比論壇中看帖就返回Etag,減小論壇負擔。

五、Etag在不一樣URL之間沒有可比性,也就是不一樣URL相同Etag沒有特別意義。

Etag的原理

請求流程

Etag由服務器端生成,客戶端經過If-Match或者說If-None-Match這個條件判斷請求來驗證資源是否修改。常見的是使用If-None-Match。請求一個文件的流程可能以下:

====第一次請求===

1.客戶端發起 HTTP GET 請求一個文件;

2.服務器處理請求,返回文件內容和一堆Header,固然包括Etag(例如"2e681a-6-5d044840")(假設服務器支持Etag生成和已經開啓了Etag)。狀態碼200。

====第二次請求===

1.客戶端發起 HTTP GET 請求一個文件,注意這個時候客戶端同時發送一個If-None-Match頭,這個頭的內容就是第一次請求時服務器返回的Etag:2e681a-6-5d044840

2.服務器判斷髮送過來的Etag和計算出來的Etag匹配,所以If-None-Match爲False,不返回200,返回304,客戶端繼續使用本地緩存;

流程很簡單,問題是,若是服務器又設置了Cache-Control:max-age和Expires呢,怎麼辦?

答案是同時使用,也就是說在徹底匹配If-Modified-Since和If-None-Match即檢查完修改時間和Etag以後,服務器才能返回304.(不要陷入到底使用誰的問題怪圈)

Etag的做用

Etag 主要爲了解決 Last-Modified 沒法解決的一些問題。

一、一些文件也許會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET。

二、某些文件修改很是頻繁,好比在秒如下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒)。

三、某些服務器不能精確的獲得文件的最後修改時間;

爲此,HTTP/1.1引入了 Etag(Entity Tags)。Etag僅僅是一個和文件相關的標記,能夠是一個版本標記,好比說v1.0.0或者說"2e681a-6-5d044840"這麼一串看起來很神祕的編碼。可是HTTP/1.1標準並無規定Etag的內容是什麼或者說要怎麼實現,惟一規定的是Etag須要放在""內。

3.3 結束

關於緩存的內容到此告一段落,對於強緩存和協商緩存,不一樣的瀏覽器和不一樣的用戶操做行爲,都有產生不一樣的請求操做,對於各個版本的瀏覽器都須要進行詳細的兼容性分析。

相關文章
相關標籤/搜索