通俗易懂的瀏覽器緩存講解

寫做背景

  • 在網絡上,介紹信息類,傳遞資訊類的文章有不少,但真正讓讀者理解的文章卻不多。
  • 筆者想作的,是結合本身的理解,將資訊以通俗易懂的方式表達出來。
  • 讓讀者不只僅瞭解該項技術,更理解其原理,清楚其流程,真正掌握它。
  • 筆者技術水平有限,文章可能有錯誤,遺漏的地方。敬請指導,期待與您的交流。

    Momo圖

緩存狀態碼

200

  • 運行流程:【瀏覽器】--(200 form cache)--》【瀏覽器緩存】--》【頁面展現】
  • 瀏覽器不須要向服務器發起請求,而是直接調用瀏覽器緩存的頁面進行展現。

304

  • 運行流程:【瀏覽器】--》【服務器】--(304)--》【瀏覽器】--》【瀏覽器緩存】--》【頁面展現】
  • 瀏覽器向服務器發起請求,並在請求頭中攜帶該頁面的特徵值,如「最後修改時間」,「頁面內容 hash 值」等。
  • 服務器接收到請求,對比請求頭中攜帶的特徵值,與服務器中頁面的特徵值是否一致。若是特徵值沒有變化,則認爲該頁面內容未發生變化,只返回 304 狀態碼的響應頭,響應體爲空。css

    • 通常而言,這部分邏輯,是不須要開發者手動實現的,是框架自帶的。
    • 固然,開發者也能夠經過某些設置關閉該功能,即直接返回服務器中的內容,無論與瀏覽器中緩存的是否是同樣。
  • 瀏覽器接收到 304 響應頭,調用瀏覽器緩存中的頁面,進行內容展現。

什麼狀況下出現 304,何時出現 200 form cache ?

對於緩存過的頁面,該頁面的「URL的直接資源」會進行 304 處理,頁面中須要加載的資源將進行 200 form cache 處理html

譬如

http://www.mongoosejs.net/docs/schematypes.html 這個頁面。前端

  • http://www.mongoosejs.net/docs/schematypes.html 直接指向的 html, 即該頁面的「URL的直接資源」,會進行 304 處理。
  • 除了接口之外,該 html 中須要加載的「其餘資源」,如 css,js,圖片等資源,都屬於 200 form cache 資源。不管該資源是經過 html 中的標籤載入,仍是經過 js 代碼,動態載入。都屬於「其餘資源」。

爲何這樣設計呢?

  • 由於該頁面的「URL的直接資源」,是該頁面的首個資源,須要訪問服務器肯定該頁面是否有更新,須要給服務器更新資源的機會。若是個資源都不訪問服務器,不與服務器溝通,那就沒法得知服務器是否有資源更新。因此不管如何設置,調用頁面的首個資源都是應當訪問服務器的。
  • 而對於「其餘資源」,不管「URL的直接資源」是否有變化,即便「URL的直接資源」 返回的不是 304,而是全新的內容,只要裏面描述的「其餘資源」對應 URL 沒有變化。那瀏覽器在必定時間內(什麼時間,後面會介紹到),都會直接調用緩存中的文件, 200 form cache。
  • 若是「URL的直接資源」(html)描述的「其餘資源」(如,css,js)的 URL 發送了變化,瀏覽器就會當作新的資源文件,從服務器中從新獲取(注意,是當作新資源獲取,而不是判斷是否更新的 304。由於是當作新的資源,而不是改變後的資源)。
  • 爲何「其餘資源」不像「URL的直接資源」那樣,訪問服務器判斷更新?不訪問怎麼知道有沒有更新呢?瀏覽器

    • 爲何不訪問服務器,由於這類資源的量通常比較多,即便內容沒有發生變化,只返回 304,也須要通過 TCP 的三次握手和四次揮手。並且瀏覽器有同一域名的併發訪問數量限制,都是須要消耗時間的。一旦資源大,這個時間成本就不可忽略了。因此不訪問服務器,直接從瀏覽器緩存取。
    • 若是這些資源真的有變化怎麼辦?修改其對應的連接,把他當作新資源訪問,經過修改「URL的直接資源」中的代碼。哪怕是在後面加些參數,如加個時間串?v=20191120122038。瀏覽器也會當作新的資源。從服務器加載。
  • 因此即便你「其餘資源」內容變化了,「URL的直接資源」沒有改變(致使 html 中 css 的 URL 沒有變化),對應的「其餘資源」都直接調用緩存中的內容,不通過服務器,這也是前端同窗常常遇到的,沒法顯示最新效果的「緩存問題」。
  • 那是否是隻有我不修改連接,就永遠都不從新訪問資源了呢?不是的,資源會有過時時間,若是超過了過時時間,就會從新訪問服務器了。下一節會對其進行介紹。

各緩存頭(請求頭,響應頭)

強緩存

服務端經過響應頭告訴瀏覽器,「接下來的一段時間」內,直接使用緩存內容。緩存

  • 有沒有以爲很熟悉?沒錯,這就是應用在「其餘資源」中的技術。爲何訪問「其餘資源」時,不連接服務器,直接從瀏覽器緩存拿。由於這是服務器告訴瀏覽器的,也就是說,是服務端讓瀏覽器從緩存中取的。不是瀏覽器自做主張設置的。
  • 那麼「接下來的一段時間」是指那段時間呢?這是由服務器經過響應頭告訴瀏覽器的。具體用到的響應頭以下:
  • (http1.0)服務器

    • Expires:標識該資源過時的絕對時間,如Thu, 21 Nov 2019 00:10:44 GMT,這代表該資源於 2019年11月21日 00時11分44秒過時。在該時間點以前訪問,則讓瀏覽器直接從緩存上取。
  • (http1.1)網絡

    • Cache-Control:接受多個參數,其中一個參數是定義過時時間。如Cache-Control: public, max-age=31536000,其中 max-age=31536000就是告知瀏覽器,在接收到該文件那一刻算起的 31536000 秒內有效,直接從瀏覽器緩存上取。

協商緩存

瀏覽器會向服務端發起http請求,而後服務端告訴瀏覽器文件未改變,讓瀏覽器使用本地緩存。使用 Ctrl+F5強制刷新可使得緩存無效併發

  • 是的,這就是「URL的直接資源」應用的技術,協商緩存返回的就是 304 狀態碼。具體用到的響應頭,請求頭以下:
  • (http1.0)框架

    • Last-Modified/If-Modified-Since
    • 其中,在首次得到資源時,服務端攜帶的相應頭是 Last-Modified,告訴瀏覽器該文件的最後修改時間。
    • 在瀏覽器再次發起請求時,就會將 Last-Modified 的值,攜帶到請求頭中,並以 If-Modified-Since 爲 key 保存。
    • 服務器在接收到 Last-Modified 請求頭後,會與本地文件的修改時間進行比對,判斷文件是否有變化,若是沒有變化,則返回 304 狀態碼。
  • (http1.1)E-tag/If-None-Matchmongoose

    • 與 Last-Modified/If-Modified-Since 相似,只是判斷的方式不一樣,Last-Modified/If-Modified-Since 是用修改時間進行判斷,If-None-Match/E-tag 則是經過文件內容的 hash 進行判斷。此判斷標準更加完全,準確。
    • 在首次得到資源時,服務端攜帶的響應頭是 E-tag。告訴瀏覽器該文件內容的 hash 值。
    • 在瀏覽器再次發起請求時,將 E-tag 的值,攜帶到請求頭中,並以 If-Modified-Since 爲 key 保存。
    • 服務器在接收到 If-Modified-Since 請求頭後,會與本地文件的 hash 值進行比對,判斷文件是否有變化,若是沒有變化,則返回 304 狀態碼。
  • 若是同時帶有E-tag和Last-Modified,服務端會優先檢查E-tag。

講完了

相關文章
相關標籤/搜索