http請求作爲影響前端性能極爲重要的一環,由於請求受網絡影響很大,若是網絡很慢的狀況下,頁面極可能會空白好久。對於首次進入網站的用戶可能要經過優化接口性能和接口數量來解決。可是,對於重複進入頁面的用戶,除了瀏覽器緩存,http緩存能夠很大程度對已經加載過的頁面進行優化。css
從緩存位置上來看,分爲4種,從上往下依次檢查是否命中,若是但都沒有命中則從新發起請求。
Service Worker 是運行在瀏覽器背後的獨立線程,通常能夠用來實現緩存功能。使用 Service Worker的話,傳輸協議必須爲 HTTPS。
Memory Cache 也就是內存中的緩存,主要包含的是當前中頁面中已經抓取到的資源,例如頁面上已經下載的樣式、腳本、圖片等。讀取內存中的數據確定比磁盤快,內存緩存雖然讀取高效,但是緩存持續性很短,會隨着進程的釋放而釋放。 一旦咱們關閉 Tab 頁面,內存中的緩存也就被釋放了。
內存緩存中有一塊重要的緩存資源是preloader相關指令(例如<link rel="prefetch">)下載的資源。它能夠一邊解析js/css文件,一邊網絡請求下一個資源。
Disk Cache 也就是存儲在硬盤中的緩存,讀取速度慢點,可是什麼都能存儲到磁盤中,比之 Memory Cache 勝在容量和存儲時效性上。
絕大部分的緩存都來自Disk Cache,在HTTP 的協議頭中設置。
Push Cache(推送緩存)是 HTTP/2 中的內容,當以上三種緩存都沒有命中時,它纔會被使用。它只在會話(Session)中存在,一旦會話結束就被釋放,而且緩存時間也很短暫,在Chrome瀏覽器中只有5分鐘左右,同時它也並不是嚴格執行HTTP頭中的緩存指令。html
下面主要說一下前端優化能入手的地方,也就是強緩存和協商緩存,而且緩存策略都是經過設置 HTTP Header 來實現的。前端
瀏覽器在第一次訪問接口後的response headers裏會攜帶一些字段,這些字段決定關於這個請求的緩存狀況,
與強緩存相關的header字段有兩個:html5
一、expires:過氣網紅,這是http1.0時的規範;它的值爲一個絕對時間的GMT格式的時間字符串,如Mon, 10 Jun 2015 21:31:12 GMT,若是發送請求的時間在expires以前,那麼本地緩存始終有效,不然就會發送請求到服務器來獲取資源web
二、cache-control:新星:max-age=number,這是http1.1時出現的header信息,主要是利用該字段的max-age值來進行判斷,它是一個相對值;資源第一次的請求時間和Cache-Control設定的有效期,計算出一個資源過時時間,再拿這個過時時間跟當前的請求時間比較,若是請求時間在過時時間以前,就能命中緩存,不然就不行;
no-cache:不使用本地緩存。須要使用協商緩存,先與服務器確認返回的響應是否被更改,若是以前的響應中存在ETag,那麼請求的時候會與服務端驗證,若是資源未被更改,則能夠避免從新下載。數據庫
no-store:直接禁止遊覽器緩存數據,每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源。瀏覽器
public:能夠被全部的用戶緩存,包括終端用戶和CDN等中間代理服務器。緩存
private:只能被終端用戶的瀏覽器緩存,不容許CDN等中繼緩存服務器對其緩存。
注意:若是cache-control與expires同時存在的話,cache-control的優先級高於expires安全
強緩存時段命中,會直接從緩存中返回數據,返回值200;這一時間段,無論接口內容有沒有變化都不會進行請求更新。服務器
當沒有強緩存時,會向服務端尋求幫助,也就是問一下服務端有沒有更改,向接口判斷是否有緩存。若是命中協商緩存則返回304狀態碼,而且從本地返回緩存內容。若是沒有命中,則從新發起請求。
協商緩存須要跟服務端經過特殊標示鏈接,即第一次請求的響應頭帶上某個字段(Last-Modified或者Etag),則後續請求則會帶上對應的請求字段(If-Modified-Since或者If-None-Match),若響應頭沒有Last-Modified或者Etag字段,則請求頭也不會有對應的字段。
具體過程以下:
Last-Modified/If-Modified-Since
1.瀏覽器第一次跟服務器請求一個資源,respone的header里加上Last-Modified:表示這個資源在服務器上的最後修改時間
2.瀏覽器再次跟服務器請求這個資源時,在request的header上加上If-Modified-Since的header:上一次請求時返回的Last-Modified的值
3.服務器再次收到資源請求時,會判斷最後修改時間是否有變化,若是沒有變化則返回304 Not Modified,可是不會返回資源內容;若是有變化,就正常返回資源內容,Last-Modified會被修改成最新的值。若是沒有變化,服務器返回304 Not Modified,Last-Modified不會修改,response header中不會再添加Last-Modified的header
4.瀏覽器收到304的響應後,就會從緩存中加載資源
Etag/If-None-Match
由服務器生成的每一個資源的惟一標識字符串,只要資源有變化就這個值就會改變;其判斷過程與Last-Modified/If-Modified-Since相似,與Last-Modified不同的是,當服務器返回304 Not Modified的響應時,因爲ETag從新生成過,response header中還會把這個ETag返回,即便這個ETag跟以前的沒有變化。
1.一些文件也許會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET;
2.某些文件修改很是頻繁,好比在秒如下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒);
3.某些服務器不能精確的獲得文件的最後修改時間。
Last-Modified與ETag是能夠一塊兒使用的,服務器會優先驗證ETag,一致的狀況下,纔會繼續比對Last-Modified,最後才決定是否返回304。
瀏覽器本地緩存最經常使用的是cookie、localStroage、sessionStroage、webSql、indexDB。
cookie的用法很簡單,能夠經過服務端設置,js也能夠經過documnet.cookie="名稱=值;"(不要忘記以;分割)來設置。
cookie的值字符串能夠用encodeURIComponent()來保證它不包含任何逗號、分號或空格(cookie值中禁止使用這些值).
cookie通常用作爲登錄態保存、密碼、我的信息等關鍵信息保存使用,因此爲了安全也是遵照同源策略原則的。
能夠經過下面參數具體設置:
;path=path (例如 '/', '/mydir') 若是沒有定義,默認爲當前文檔位置的路徑。
;domain=domain (例如 'example.com', 'subdomain.example.com') 若是沒有定義,默認爲當前文檔位置的路徑的域名部分。與早期規範相反的是,在域名前面加 . 符將會被忽視,由於瀏覽器也許會拒絕設置這樣的cookie。若是指定了一個域,那麼子域也包含在內。
;max-age=max-age-in-seconds (例如一年爲606024*365)
;expires=date-in-GMTString-format 若是沒有定義,cookie會在對話結束時過時這個值的格式參見Date.toUTCString()
;secure (cookie只經過https協議傳輸)
;HttpOnly 限制web頁面程序的browser端script程序讀取cookie
缺點
容量有限制,不能超過4kb
在請求頭上帶着數據安全性差
html5新增本地存儲,localStorage生命週期是永久,除非主動清除localStorage信息,不然這些信息將永遠存在。存放數據大小爲通常爲5MB,sessionStorage僅在當前會話下有效,關閉頁面或瀏覽器後被清除。並且它僅在客戶端(即瀏覽器)中保存,不參與和服務器的通訊。也是遵照同源策略原則的
// 一、保存數據到本地 // 第一個參數是保存的變量名,第二個是賦給變量的值 localStorage.setItem('key', 'value'); //複雜類型儲存須要**利用JSON.stringify**將對象轉換成字符串; //利用**JSON.parse**將字符串轉換成對象 // 二、從本地存儲獲取數據 localStorage.getItem('key'); // 三、從本地存儲刪除某個已保存的數據 localStorage.removeItem('key'); // 四、清除全部保存的數據 localStorage.clear();
WebSQL是前端的一個獨立模塊,是web存儲方式的一種,咱們調試的時候會常常看到,只是通常不多使用。而且,當前只有谷歌支持,ie和火狐均不支持。
主要方法:
1.openDatabase:這個方法使用現有的數據庫或者新建的數據庫建立一個數據庫對象。
2.transaction:這個方法讓咱們可以控制一個事務,以及基於這種狀況執行提交或者回滾。
3.executeSql:這個方法用於執行實際的 SQL 查詢。
IndexedDB 就是瀏覽器提供的本地數據庫,它能夠被網頁腳本建立和操做。IndexedDB 容許儲存大量數據,提供查找接口,還能創建索引。這些都是 LocalStorage 所不具有的。就數據庫類型而言,IndexedDB 不屬於關係型數據庫(不支持 SQL 查詢語句),更接近 NoSQL 數據庫。
具體概念參考:參考文章