瀏覽器緩存,想說愛你不容易

来源:http://www.cnblogs.com/depsi/archive/2016/06/13/5579648.html
-Advertisement-
Play Games

今天小微開店寶在測試環境發佈更新的時候,同事問:“**為什麼我需要手動清理瀏覽器緩存才能看到變更?難道系統上線後也需要客戶自己清理瀏覽器緩存嗎!”看來,這個坑需要我來填了。 ...


  今天小微開店寶在測試環境發佈更新的時候,同事問:“為什麼我需要手動清理瀏覽器緩存才能看到變更?難道系統上線後也需要客戶自己清理瀏覽器緩存嗎!”看來,這個坑需要我來填了。

什麼是瀏覽器緩存

瀏覽器緩存(Brower Caching)是瀏覽器在本地磁碟對用戶最近請求過的文檔進行存儲,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁碟載入文檔。

瀏覽器緩存的優點有:

  1. 減少了冗餘的數據傳輸,節省了網費
  2. 減少了伺服器的負擔,大大提升了網站的性能
  3. 加快了客戶端載入網頁的速度

在前端開發麵試中,瀏覽器緩存是web性能優化面試題中很重要的一個知識點,從而說明瀏覽器緩存是提升web性能的一大利器,但是瀏覽器緩存如果使用不當,也會產生很多問題,正所謂是,想說愛你,並不是很容易的事。所以,結合最近遇到的案例,本文對瀏覽器緩存相關的知識進行總結歸納,希望對讀者有所幫助。

瀏覽器緩存的分類

瀏覽器緩存主要有兩類:緩存協商徹底緩存,也有稱之為協商緩存強緩存

瀏覽器在第一次請求發生後,再次請求時:

  1. 瀏覽器會先獲取該資源緩存的header信息,根據其中的expirescahe-control判斷是否命中強緩存,若命中則直接從緩存中獲取資源,包括緩存的header信息,本次請求不會與伺服器進行通信;
  2. 如果沒有命中強緩存,瀏覽器會發送請求到伺服器,該請求會攜帶第一次請求返回的有關緩存的header欄位信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由伺服器根據請求中的相關header信息來對比結果是否命中協商緩存,若命中,則伺服器返回新的響應header信息更新緩存中的對應header信息,但是並不返回資源內容,它會告知瀏覽器可以直接從緩存獲取;否則返回最新的資源內容

強緩存

強緩存是利用http的返回頭中的Expires或者Cache-Control兩個欄位來控制的,用來表示資源的緩存時間。

Expires
該欄位是http1.0時的規範,它的值為一個絕對時間的GMT格式的時間字元串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT。這個時間代表著這個資源的失效時間,在此時間之前,即命中緩存。這種方式有一個明顯的缺點,由於失效時間是一個絕對時間,所以當伺服器與客戶端時間偏差較大時,就會導致緩存混亂。

Cache-Control
Cache-Control是http1.1時出現的header信息,主要是利用該欄位的max-age值來進行判斷,它是一個相對時間,例如Cache-Control:max-age=3600,代表著資源的有效期是3600秒。cache-control除了該欄位外,還有下麵幾個比較常用的設置值:

  • no-cache:不使用本地緩存。需要使用緩存協商,先與伺服器確認返回的響應是否被更改,如果之前的響應中存在ETag,那麼請求的時候會與服務端驗證,如果資源未被更改,則可以避免重新下載。
  • no-store:直接禁止游覽器緩存數據,每次用戶請求該資源,都會向伺服器發送一個請求,每次都會下載完整的資源。
  • public:可以被所有的用戶緩存,包括終端用戶和CDN等中間代理伺服器。
  • private:只能被終端用戶的瀏覽器緩存,不允許CDN等中繼緩存伺服器對其緩存。

Cache-Control與Expires可以在服務端配置同時啟用,同時啟用的時候Cache-Control優先順序高。

協商緩存

協商緩存就是由伺服器來確定緩存資源是否可用,所以客戶端與伺服器端要通過某種標識來進行通信,從而讓伺服器判斷請求資源是否可以緩存訪問,這主要涉及到下麵兩組header欄位,這兩組搭檔都是成對出現的,即第一次請求的響應頭帶上某個欄位(Last-Modified或者Etag),則後續請求則會帶上對應的請求欄位(If-Modified-Since或者If-None-Match),若響應頭沒有Last-Modified或者Etag欄位,則請求頭也不會有對應的欄位。

Last-Modify/If-Modify-Since

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

當瀏覽器再次請求該資源時,request的請求頭中會包含If-Modify-Since,該值為緩存之前返回的Last-Modify。伺服器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存。

如果命中緩存,則返回304,並且不會返回資源內容,並且不會返回Last-Modify。

ETag/If-None-Match

與Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一個校驗碼。ETag可以保證每一個資源是唯一的,資源變化都會導致ETag變化。伺服器根據瀏覽器上送的If-None-Match值來判斷是否命中緩存。

與Last-Modified不一樣的是,當伺服器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化。

為什麼要有Etag

你可能會覺得使用Last-Modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,為什麼還需要Etag呢?HTTP1.1中Etag的出現主要是為瞭解決幾個Last-Modified比較難解決的問題:

  • 一些文件也許會周期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認為這個文件被修改了,而重新GET;
  • 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
  • 某些伺服器不能精確的得到文件的最後修改時間。

Last-Modified與ETag是可以一起使用的,伺服器會優先驗證ETag,一致的情況下,才會繼續比對Last-Modified,最後才決定是否返回304。

強緩存與協商緩存的區別可以用下表來表示:
 |獲取資源形式|狀態碼|發送請求到伺服器
------|------------|------|----------------
強緩存|從緩存取 |200(from cache)|否,直接從緩存取
協商緩存|從緩存取|304(Not Modified)|否,通過伺服器來告知緩存是否可用

用戶行為對緩存的影響

用戶操作 Expires/Cache-Control Last-Modied/Etag
地址欄回車 有效 有效
頁面鏈接跳轉 有效 有效
新開視窗 有效 有效
前進回退 有效 有效
F5刷新 無效 有效
Ctrl+F5強制刷新 無效 無效

實際問題分析

如文章開頭所屬,代碼更新到線上後用戶瀏覽器不能自行更新,我們不能要求客戶在系統更新後都進行一次緩存清理的操作。

到底該如何解決呢?

在資源請求的URL中增加一個參數,比如:js/mian.js?ver=0.7.1。這個參數是一個版本號,每一次部署的時候變更一下,當這個參數變化的時候,強緩存都會失效並重新載入。這樣一來,靜態資源,部署以後就需要重新載入。這樣就比較完美的解決了問題。

進一步思考

這樣做是不是最完美的呢?很遺憾,不是。

百度張雲龍給出了這樣做的弊端,有興趣可參照下文:
靜態資源版本更新與緩存

謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • .bottomTable{ background-color: rgb(249,249,249); z-index:99999999; position:fixed; bottom:0; left:0; width:100%; _position:absolute; /* for IE6 */ /* ...
  • javascript的列印輸出document.write() 1 document.write(hello world !); ...
  • 效果展示 http://hovertree.com/texiao/jquery/77/看慣了左右切換的幻燈片,何問起向您推薦一個新穎的,旋轉切換,通過點擊按鈕的相應區域可以使幻燈片以旋轉的方式來切換圖片,非常有創意。點擊哪個顏色就切換到那個顏色,還帶音效。背景圖可以自定義。進入源碼下載頁面 http ...
  • React作為目前最流行的前端框架之一,其受歡迎程度不容小覷,從這門框架上我們可以學到許多其他前端框架所缺失的東西,也是其創新性所在的地方,比如虛擬DOM、JSX等。那麼接下來我們就來學習一下這門框架是如何構建起一個單頁應用的。 前言 首先在學習這門框架前,你需要對以下知識有所瞭解: 原生JS基礎 ...
  • 在mvc/mvvm類框架出現之前,開發者通常需要手動更新html並維護html與數據之間的關係。隨著mvc思想在前端社區的普及和發展,view層和model層的解耦和分離機制已經是各框架的標配了。令人欣喜的是,angular2在現有各框架的理論基礎上對數據綁定重新進行了抽象,在架構上進行了革新,很有 ...
  • 通過Object構造函數或對象字面量創建對象時,使用同一個介面創建很多對象時,會產生大量的重覆代碼。為了簡化,引入了工廠模式。 工廠模式 function createPerson(name, age, job) { var obj = new Object(); obj.name = name; ...
  • 斷點,調試器的功能之一,可以讓程式中斷在需要的地方,從而方便其分析。也可以在一次調試中設置斷點,下一次只需讓程式自動運行到設置斷點位置,便可在上次設置斷點的位置中斷下來,極大的方便了操作,同時節省了時間。 ——百度百科 簡單地說,斷點調試是指自己在程式的某一行設置一個斷點,調試時,程式運行到這一行就 ...
  • 解決backbone url請求中參數有中文,存入資料庫是亂碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...