瀏覽器的緩存策略

在前端開發(fā)中,性能一直是被大家所重視的一點,然而判斷一個網(wǎng)站的性能最直觀的就是看網(wǎng)頁打開的速度。其中提高網(wǎng)頁反應(yīng)速度的一個方式就是使用緩存。一個優(yōu)秀的緩存策略可以縮短網(wǎng)頁請求資源的距離,減少延遲,并且由于緩存文件可以重復利用,還可以減少帶寬,降低網(wǎng)絡(luò)負荷。

緩存分類

web緩存分為很多種,比如數(shù)據(jù)庫緩存、代理服務(wù)器緩存、還有CDN緩存,以及瀏覽器緩存

瀏覽器先向代理服務(wù)器發(fā)起web請求,再將請求轉(zhuǎn)發(fā)到源服務(wù)器。代理服務(wù)器屬于共享緩存,所以很多地方都可以使用其緩存資源,因此對于節(jié)省流量有很大的作用

瀏覽器緩存是將文件保存在客戶端,在同一個會話過程中會檢查緩存的副本是否足夠新,在后退網(wǎng)頁時,訪問過的資源可以從瀏覽器緩存中拿出來使用。

瀏覽器緩存

頁面的緩存狀態(tài)是由header決定的,header的參數(shù)有四種

一、cache-control(重要策略)

cache-control包括max-age/s-maxage/public/private/no-cache/no-store/must-revalidate等

1、max-age(單位為s)指定設(shè)置緩存最大的有效時間,定義的是時間長短。當瀏覽器向服務(wù)器發(fā)送請求后,在max-age這段時間里瀏覽器就不會再向服務(wù)器發(fā)送請求了。
2、 s-maxage 為代理服務(wù)器設(shè)置不同的緩存策略

對于熟悉http的人來說,max-age不僅在cache-control中使用,連cookie都會用到。s-maxage在一些小項目中可能并不會用到,但是在基于各種代理的大型架構(gòu)中就需要考慮代理服務(wù)器的緩存問題。

每一層代理都有自己的緩存機制。如果是一層完全基于http的代理,應(yīng)用服務(wù)器的緩存機制就會在代理服務(wù)器上被應(yīng)用。對于一些不會改變的靜態(tài)資源,我們希望客戶端一直緩存下去,這時候我們通常會設(shè)置max-age=31536000(一年)之類的,但是如果代理服務(wù)器也遵循h(huán)ttp緩存的規(guī)范,這個max-age就會被應(yīng)用。也就是說,代理服務(wù)器也會緩存這個資源一年。這不是在浪費代理服務(wù)器的磁盤空間么。所以我們有時候會對代理服務(wù)器使用一些不一樣的緩存策略。比如我們雖然讓客戶端緩存一年,但是希望讓代理服務(wù)器緩存一天就夠了。于是在設(shè)置max-age=31536000的同時還可以設(shè)置s-maxage=86400

標準的http代理服務(wù)器都實現(xiàn)了s-maxage的解析,比如nginx,我們可以在它的http_upstream模塊中找到實現(xiàn)的代碼。但一些其他兼職的http代理服務(wù)器上,實現(xiàn)方式就很奇奇怪怪的了。

s-maxage是一個在RFC2616中就定義的東西。規(guī)范定義了代理服務(wù)器會優(yōu)先考慮s-maxage,所以我們才可以對代理服務(wù)器和終端用戶設(shè)置不同的緩存策略

  1. public指定響應(yīng)會被緩存,并且在多用戶間共享。如果沒有指定public還是private,則默認為public。public表明響應(yīng)可以被任何對象(包括發(fā)送請求的客戶端、代理服務(wù)器等等)緩存
  2. private響應(yīng)只作為私有的緩存,不能在用戶間共享。如果要求http認證,響應(yīng)會自動設(shè)置為private。表明響應(yīng)只能被單個用戶緩存,不能作為共享緩存,所以代理服務(wù)器不能緩存它
  3. no-cache指定不緩存響應(yīng),表明資源不進行緩存。但是設(shè)置了no-cache之后并不代表瀏覽器不緩存,而是在緩存前要向服務(wù)器確認資源是否被更改。因此有時候只設(shè)置no-cache防止緩存還是不夠保險,還可以加上private指令,將過期時間設(shè)為過去的時間。

禁用緩存:
cache-conctrol:no-cache,no-store,must-revalidate

  1. no-store絕對禁止緩存,一看就知道如果用了這個命令當然就不會進行緩存,每次請求資源都要從服務(wù)器重新獲取。
  2. must-revalidate緩存必須在使用之前驗證舊資源的狀態(tài),并且不可使用過期資源。
  • no-cache:告訴瀏覽器、代理服務(wù)器,不管本地副本是否過期,在使用資源副本之前,一定要到源服務(wù)器進行副本有效性校驗
  • must-revalidate: 告訴瀏覽器、緩存服務(wù)器,本地副本過期前,可以使用本地副本;本地副本一旦過期,必須去源服務(wù)器進行有效性校驗。

二、 Expires

緩存的過期時間,用來指定資源到期的時間,是服務(wù)器端的具體時間點。也就是說Expires=max-age+請求時間,需要和last-modified結(jié)合使用。但是上面提到,cache-control的優(yōu)先級更高。Expires是web服務(wù)器響應(yīng)消息頭字段,在響應(yīng)http請求時告訴瀏覽器過期時間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù),而無需再次請求。

三、 Last-modified

服務(wù)器端文件的最后修改時間,需要和cache-control共同使用,是檢查服務(wù)器端資源是否更新的一種方式。當瀏覽器再次進行請求時,會向服務(wù)器傳送if-modified-since報頭,詢問last-modified時間點之后資源是否修改過。如果沒有修改,則返回304,使用緩存;如果修改過,則再去服務(wù)器請求資源,返回碼為200.

四、 ETag

根據(jù)實體內(nèi)容生成一段hash字符串,標識資源的狀態(tài),由服務(wù)端產(chǎn)生。瀏覽器會將這串字符串傳回服務(wù)器,驗證資源是否已經(jīng)修改。如果沒有修改,則過程如下

客戶端----請求頁面a---->服務(wù)器

客戶端<----頁面+ETag----服務(wù)器

客戶端----再次請求頁面a+Etag---->服務(wù)器

服務(wù)器----檢查ETag---->服務(wù)器

客戶端<----304+空響應(yīng)----服務(wù)器

使用ETag可以解決last-modified存在的一些問題

  • 某些服務(wù)器不能精確得到資源的最后修改時間,這樣就無法通過最后修改時間判斷資源是否更新
  • 如果資源修改非常頻繁,在秒以下的時間內(nèi)進行修改,而last-modified只能精確到秒
  • 一些資源的最后修改時間變了,但是內(nèi)容沒變,使用ETag就認為資源還是沒有修改

使用緩存的流程

設(shè)置緩存的方法

第一種:HTML Meta標簽控制緩存(非HTTP協(xié)議定義)

<meta http-equiv="Pragma" content="no-cache">
上述代碼的作用是告訴瀏覽器當前頁面不被緩存,每次訪問都需要去服務(wù)器拉取。這種方法使用時很簡單,但是只有部分瀏覽器可以支持,而且所有的緩存代理服務(wù)器都不支持,因為代理不解析HTML內(nèi)容本身。

第二種 HTTP頭信息控制緩存

HTTP頭信息控制緩存是通過Expires(強緩存)、cache-control(強緩存)、Last-Modified/if-Modified-Since(協(xié)商緩存)、ETag/if-None-Match(協(xié)商緩存)實現(xiàn)。

1. Expires

Expires是http1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間,由服務(wù)器返回,用GMT格式的字符串表示

缺點:Expries是較老的強緩存管理header,由于他是服務(wù)器返回的一個絕對時間,這樣就存在一個問題,如果客戶端的時間與服務(wù)器的時間相差很大(比如時鐘不同步,或者跨時區(qū)),那么誤差就很大,所以在HTTP1.1版本開始,使用cache-control:max-age=秒代替。

2. cache-control

cache-control描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷,所以相比較Expires,cache-control的緩存管理更有效,更安全一點

cache-control的值可以是public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age

各個消息中的指令含義如下:
public指示響應(yīng)可被任何緩存區(qū)緩存

private指示對于單個用戶的整個或部分響應(yīng)消息,不能被共享緩存處理。這允許服務(wù)器僅僅描述當前用戶的部分響應(yīng)消息,此響應(yīng)消息對于其他用戶的請求無效。

no-cache指示請求或響應(yīng)消息不能緩存,該選項并不是說可以設(shè)置“不緩存”,而是需要和服務(wù)器確認。

no-store在請求消息中發(fā)送將使得請求和響應(yīng)消息都不使用緩存,完全不存下來

max-age指示客戶端可以接收生存期可以不大于指定時間(以秒為單位)的響應(yīng),上次緩存時間(客戶端的)+max-age(64200s)< 客戶端時間

min-fresh指示客戶端可以接收響應(yīng)時間小于當前時間加上指定時間的響應(yīng)

max-stale指示客戶端可以接收超出超時期內(nèi)的響應(yīng)消息。如果指定max-stale消息的值,那么客戶端可以接收超出超時期指定值之內(nèi)的響應(yīng)消息。

注意:這兩個header可以只啟用一個,也可以同時啟用,當response header中,expires和cache-control同時存在時,cache-control優(yōu)先級高于expires

3. Last-Modifiied/if-Modified-Since

Last-Modified-Since要配合Cache-Control使用

Last-Modified:標識這個響應(yīng)資源的最后修改時間。web服務(wù)器在響應(yīng)請求時,告訴瀏覽器資源的最后修改時間

if-Modified-Since:當資源過期時(強緩存失效),發(fā)現(xiàn)資源具有Last-modified聲明,則再次向web服務(wù)器請求時帶上頭if-Modified-Since,表示請求時間。web服務(wù)器收到請求后發(fā)現(xiàn)有頭If-Modified-Since,則與被請求資源的最后修改時間進行比對。若最后修改時間較新,說明資源又被改動過,則響應(yīng)整片資源內(nèi)容(寫在響應(yīng)消息包體內(nèi)),HTTP200;若最后修改時間較舊,說明資源無新修改,則響應(yīng)HTTP 304(無需包體,節(jié)省瀏覽),告訴瀏覽器繼續(xù)使用所保存的cache。

4. ETag/if-none-match

ETag/if-none-match也要配合cache-control使用

ETag:web服務(wù)器響應(yīng)請求時,告訴瀏覽器當前資源在服務(wù)器的唯一標識(生成規(guī)則由服務(wù)器制定)。apache中,ETag的值,默認是對文件的索引節(jié)(INode),大?。╯ize)和最后修改時間(MTime)進行hash后得到的。

if-none-match:當資源過期時(使用cache-control標識的max-age)發(fā)現(xiàn)資源有ETag聲明,則再次向web服務(wù)器請求時帶上if-none-match(ETag的值),web服務(wù)器收到請求后發(fā)現(xiàn)有if-none-match則與被請求資源的相應(yīng)校驗串進行比對,決定返回200還是304.

ETag是服務(wù)器自動生成或者由開發(fā)者生成的對應(yīng)資源在服務(wù)器端的唯一標志符,能夠更加準確地控制緩存。Last-Modified與ETag一起使用時,服務(wù)器會優(yōu)先驗證ETag

用戶行為與緩存

瀏覽器緩存行為還有用戶的行為有關(guān)

用戶操作 expires/cache-control last-modified/ETag
地址欄回車 有效 有效
頁面鏈接跳轉(zhuǎn) 有效 有效
新開窗口 有效 有效
前進、后退 有效 有效
f5/按鈕刷新 無效(BR重置max-age=0) 有效
ctrl+f5刷新 無效(重置cache-control=no-cache 無效(請求頭丟棄該選項)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容