工做上遇到一個這樣的需求,一個H5頁面在APP端,若是勾選已讀狀態,則下次打開該連接,會跳過此頁面。用到了HTML5 的本地存儲 API 中的 localStorage做爲解決方案,回顧了下Web緩存的知識,感受本身瞭解得不夠多,因此想整理下,加深理解。javascript
Web緩存是指一個Web資源(如html頁面,圖片,js,數據等)存在於Web服務器和客戶端(瀏覽器)之間的副本。緩存會根據進來的請求保存輸出內容的副本;當下一個請求來到的時候,若是是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求,仍是向源服務器再次發送請求。比較常見的就是瀏覽器會緩存訪問過網站的網頁,當再次訪問這個URL地址的時候,若是網頁沒有更新,就不會再次下載網頁,而是直接使用本地緩存的網頁。只有當網站明確標識資源已經更新,瀏覽器纔會再次下載網頁。css
在Web應用領域,Web緩存大體能夠分爲如下幾種類型:html
Web應用,特別是SNS類型的應用,每每關係比較複雜,數據庫表繁多,若是頻繁進行數據庫查詢,很容易致使數據庫不堪重荷。爲了提供查詢的性能,會將查詢後的數據放到內存中進行緩存,下次查詢時,直接從內存緩存直接返回,提供響應效率。好比經常使用的緩存方案有memcached等。前端
服務器端緩存包含代理服務器緩存和CDN緩存:html5
代理服務器是瀏覽器和源服務器之間的中間服務器,瀏覽器先向這個中間服務器發起Web請求,通過處理後(好比權限驗證,緩存匹配等),再將請求轉發到源服務器。代理服務器緩存的運做原理跟瀏覽器的運做原理差很少,只是規模更大。能夠把它理解爲一個共享緩存,不僅爲一個用戶服務,通常爲大量用戶提供服務,所以在減小相應時間和帶寬使用方面頗有效,同一個副本會被重用屢次。常見代理服務器緩存解決方案有Squid等,這裏再也不詳述。java
CDN(Content delivery networks)緩存,也叫網關緩存、反向代理緩存。CDN緩存通常是由網站管理員本身部署,爲了讓他們的網站更容易擴展並得到更好的性能。瀏覽器先向CDN網關發起Web請求,網關服務器後面對應着一臺或多臺負載均衡源服務器,會根據它們的負載請求,動態將請求轉發到合適的源服務器上。雖然這種架構負載均衡源服務器之間的緩存無法共享,但卻擁有更好的處擴展性。從瀏覽器角度來看,整個CDN就是一個源服務器。git
瀏覽器緩存(Browser Caching)是瀏覽器端保存數據用於快速讀取或避免重複資源請求的優化機制,有效的緩存使用能夠避免重複的網絡請求和瀏覽器快速地讀取本地數據,總體上加速網頁展現給用戶。github
應用層緩存指的是從代碼層面上,經過代碼邏輯和緩存策略,實現對數據,頁面,圖片等資源的緩存,能夠根據實際狀況選擇將數據存在文件系統或者內存中,減小數據庫查詢或者讀寫瓶頸,提升響應效率。web
接下來從Web前端的角度着重瞭解瀏覽器端緩存機制。sql
根據標準,到目前爲止,H5 一共有6種緩存機制,有些是以前已有,有些是 H5 才新加入的。
1. 瀏覽器緩存機制 2. Dom Storgage(Web Storage)存儲機制 3. Web SQL Database 存儲機制 4. Application Cache(AppCache)機制 5. Indexed Database (IndexedDB) 6. File System API
瀏覽器緩存機制,其實主要就是HTTP協議定義的緩存機制(如: Expires; Cache-control等)。可是也有非HTTP協議定義的緩存機制,如使用HTML Meta 標籤,Web開發者能夠在HTML頁面的節點中加入 標籤,代碼以下:
<META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Expires" CONTENT="0">
上述代碼的做用是告訴瀏覽器當前頁面不被緩存,每次訪問都須要去服務器拉取。使用上很簡單,但只有部分瀏覽器能夠支持,並且全部緩存代理服務器都不支持,由於代理不解析HTML內容自己。下面主要介紹HTTP協議定義的緩存機制。
經過 HTTP 協議頭裏的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等字段來控制文件緩存的機制。這應該是 WEB 中最先的緩存機制了,是在 HTTP 協議中實現的,有點不一樣於 Dom Storage、AppCache 等緩存機制,但本質上是同樣的。能夠理解爲,一個是協議層實現的,一個是應用層實現的。
(1) 最多見的,好比服務器回包:Cache-Control:max-age=600 表示文件在本地應該緩存,且有效時長是600秒(從發出請求算起)。在接下來600秒內,若是有請求這個資源,瀏覽器不會發出 HTTP 請求,而是直接使用本地緩存的文件。 (2) Cache-Control: no-cache;這個很容易讓人產生誤解,令人誤覺得是響應不被緩存。實際上她是會被緩存的,只不過每次在向客戶端(瀏覽器)提供響應數據時,緩存都要向服務器評估緩存響應的有效性。 (3) Cache-Control: no-store;這個纔是響應不被緩存的意思。
(2) If-Modified-Since:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
(1) Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器以爲)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的。 (2) If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。
你可能會以爲使用Last-Modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還須要Etag(實體標識)呢?HTTP1.1中Etag的出現主要是爲了解決幾個Last-Modified比較難解決的問題: (1) Last-Modified標註的最後修改只能精確到秒級,若是某些文件在1秒鐘之內,被修改屢次的話,它將不能準確標註文件的修改時間。 (2) 若是某些文件會被按期生成,當有時內容並無任何變化,但Last-Modified卻改變了,致使文件無法使用緩存。 (3) 有可能存在服務器沒有準確獲取文件修改時間,或者與代理服務器時間不一致等情形。 Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符,可以更加準確的控制緩存。Last-Modified與ETag是能夠一塊兒使用的,服務器會優先驗證ETag,一致的狀況下,纔會繼續比對Last-Modified,最後才決定是否返回304。
(2) 瀏覽器第二次請求: ![如圖][2]
DOM Storage 是指 HTML5 的本地存儲 API sessionStorage 和 localStorage。在介紹HTML5本地存儲以前,先來看一看前面幾個存儲方式的概念。
(1) HTTP Cookie: Cookie是爲了解決HTTP無狀態的特性而出現的,也能夠叫用戶識別機制。經常使用的用戶識別機制包括:
對於購物網站而言,cookie是很是重要的,爲了實現購物車功能,把已選物品加入cookie,能夠實現不一樣頁面之間數據的同步,同時在提交訂單的時候又會把這些cookie傳到後臺,大大方便了先後端開發。
設置cookie:
function setCookie(name, value, options) { var expires = options.expires; var path = options.path; var domain = options.domain; var secure = options.secure; // 緩存時間轉爲日期對象 if (typeof expires === 'number') { expires = new Date(new Date().getTime() + expires * 864e+5); // 緩存時間單位:天 } document.cookie = name + '=' + escape(value) + (expires ? '; expires=' + expires.toUTCString() : '') + (path ? '; path=' + path : '') + (domain ? '; domain=' + domain : '') + (secure ? '; secure' : ''); return true; }
獲取cookie:
function getCookie(name) { var arr = document.cookie.match(new RegExp('(^| )' + name + '=([^;]*)(;|$)')); if (arr !== null) { return unescape(arr[2]); } // return null; return ''; }
(2) userData是微軟在上世紀90年代的瀏覽器大戰時推出的本地存儲方案,藉助DHTML的behaviour屬性來存儲本地數據, 容許每一個頁面最多存儲64K數據,每一個站點最多640K數據,userData的缺點顯而易見,它不是Web標準的一部分,除非你的程序只須要支持IE, 不然它基本沒什麼用處。
(3) Flash cookie的名字有些誤導,它實際上和HTTP cookie並非一回事,或許它的名字應該叫作"Flash本地存儲」,Flash cookie默認容許每一個站點存儲不超過100K的數據,若是超出了,Flash會自動向用戶請求更大的存儲空間,藉助Flash的 ExternalInterface接口,你能夠很輕鬆地經過Javascript操做Flash的本地存儲。Flash的問題很簡單,就是由於它是 Flash。
(4) Gears是Google在07年發佈的一個開源瀏覽器插件,旨在改進各大瀏覽器的兼容性,Gears內置了一個基於SQLite的嵌入式 SQL數據庫,並提供了統一API對數據庫進行訪問,在取得用戶受權以後,每一個站點能夠在SQL數據庫中存儲不限大小的數據,Gears的問題就是 Google本身都已經不用它了。
(5) HTML5 的本地存儲 API sessionStorage 和 localStorage
Dom Storage 是經過存儲字符串的 Key/Value 對來提供的,並提供 5MB (不一樣瀏覽器可能不一樣,分 HOST)的存儲空間(Cookies 才 4KB)。另外 Dom Storage 存儲的數據在本地,不像 Cookies,每次請求一次頁面,Cookies 都會發送給服務器。
DOM Storage 分爲 sessionStorage 和 localStorage。localStorage 對象和 sessionStorage 對象使用方法基本相同,它們的區別在於做用的範圍不一樣。sessionStorage 用來存儲與頁面相關的數據,它在頁面關閉後沒法使用。而 localStorage 則持久存在,在頁面關閉後也可使用。
簡單用法:
var name = sessionStorage.setItem("name","wangjuan"); alert(sessionStorage.getItem("name"));
並非全部的瀏覽器都支持這兩個對象。在沒有原生支持localStorage的瀏覽器中使用時,MDN給出了兼容代碼:https://developer.mozilla.org/zh-CN/docs/Web/Guide/API/DOM/Storage#localStorage
不一樣瀏覽器對於這兩種用法的差別的兼容代碼可參考: https://github.com/mortzdk/localStorage
H5 也提供基於 SQL 的數據庫存儲機制,用於存儲適合數據庫的結構化數據。根據官方的標準文檔,Web SQL Database 存儲機制再也不推薦使用,未來也再也不維護,而是推薦使用 AppCache 和 IndexedDB。
查看更多:戳這裏
Application Cache(簡稱 AppCache)彷佛是爲支持 Web App 離線使用而開發的緩存機制。它的緩存機制相似於瀏覽器的緩存(Cache-Control 和 Last-Modified)機制,都是以文件爲單位進行緩存,且文件有必定更新機制。但 AppCache 是對瀏覽器緩存機制的補充,不是替代。
AppCache 的原理有兩個關鍵點:manifest 屬性和 manifest 文件。
W3C 官方的一個例子:
上面 HTML 文檔,引用外部一個 JS 文件和一個 GIF 圖片文件,在其 HTML 頭中經過 manifest 屬性引用了一個 appcache 結尾的文件(即manifest文件)。
緩存的結果是:咱們在 Google Chrome 瀏覽器中打開這個 HTML 連接,JS 功能正常,圖片也顯示正常。禁用網絡,關閉瀏覽器從新打開這個連接,發現 JS 工做正常,圖片也顯示正常。固然也有多是瀏覽緩存起的做用,咱們能夠在文件的瀏覽器緩存過時後,禁用網絡再試,發現 HTML 頁面也是正常的。
manifest 文件就是以 appcache 結尾的文件,是一個普通文件文件,列出了須要緩存的文件。
完整的 manifest 文件,如:
CACHE MANIFEST # 2012-02-21 v1.0.0 /theme.css /logo.gif /main.js NETWORK: login.asp FALLBACK: /html/ /offline.html
瞭解更多:戳我
IndexedDB 也是一種數據庫的存儲機制,但不一樣於已經再也不支持的 Web SQL Database。IndexedDB 不是傳統的關係數據庫,indexedDB中沒有表的概念,相似於 Dom Storage 的 key-value 的存儲方式,但功能更強大,且存儲空間更大。它的特色是:
File System API 是 H5 新加入的存儲機制。它爲 Web App 提供了一個虛擬的文件系統,就像 Native App 訪問本地文件系統同樣。因爲安全性的考慮,這個虛擬文件系統有必定的限制。Web App 在虛擬的文件系統中,能夠進行文件(夾)的建立、讀、寫、刪除、遍歷等操做。
File System API 也是一種可選的緩存機制,和前面的 SQLDatabase、IndexedDB 和 AppCache 等同樣。File System API 有本身的一些特定的優點:
瞭解更多:資料
以前對web緩存沒有系統的認知,接觸過一兩點,不過也不是很懂。這兩天查看了許多資料,雖然看過以後理解得也不太深刻,不過有個總體的認知也好,後面本身遇到相關問題再細究。
參考資料:
一、九種瀏覽器端緩存機制知多少
二、瀏覽器緩存原理
三、Web緩存機制系列
四、Web 前端實現本地存儲
五、H5 緩存機制淺析 - 移動端 Web 加載性能優化
六、瀏覽器緩存機制
七、瀏覽器緩存機制詳解
八、透過瀏覽器看HTTP緩存
九、淺談瀏覽器http的緩存機制
十、瀏覽器緩存機制淺析