瀏覽器緩存總結(cookie、localStorage、sessionStorage)


Cookie

簡介

Cookie 的本職工作並非本地存儲,而是“維持狀態”。因為HTTP協議是無狀態的,HTTP協議自身不對請求和響應之間的通信狀態進行保存,,通俗來說,服務器不知道用戶上一次做了什么,這嚴重阻礙了交互式Web應用程序的實現。在典型的網上購物場景中,用戶瀏覽了幾個頁面,買了一盒餅干和兩瓶飲料。最后結帳時,由於HTTP的無狀態性,不通過額外的手段,服務器並不知道用戶到底買了什么,於是就誕生了Cookie。它就是用來繞開HTTP的無狀態性的“額外手段”之一。服務器可以設置或讀取Cookies中包含信息,借此維護用戶跟服務器會話中的狀態。

我們可以把Cookie 理解為一個存儲在瀏覽器里的一個小小的文本文件,它附着在 HTTP 請求上,在瀏覽器和服務器之間“飛來飛去”。它可以攜帶用戶信息,當服務器檢查 Cookie 的時候,便可以獲取到客戶端的狀態。

在剛才的購物場景中,當用戶選購了第一項商品,服務器在向用戶發送網頁的同時,還發送了一段Cookie,記錄着那項商品的信息。當用戶訪問另一個頁面,瀏覽器會把Cookie發送給服務器,於是服務器知道他之前選購了什么。用戶繼續選購飲料,服務器就在原來那段Cookie里追加新的商品信息。結帳時,服務器讀取發送來的Cookie就行了。

使用場景

  • 記住密碼,下次自動登錄
  • 購物車功能
  • 記錄用戶瀏覽數據,進行商品(廣告)推薦

原理

第一次訪問網站的時候,瀏覽器發出請求,服務器響應請求后,會在響應頭里面添加一個Set-Cookie選項,將cookie放入到響應請求中,在瀏覽器第二次發請求的時候,會通過Cookie請求頭部將Cookie信息發送給服務器,服務端會辨別用戶身份,另外,Cookie的過期時間、域、路徑、有效期、適用站點都可以根據需要來指定

讀寫操作

  • 操作瀏覽器對象

    //設置
    	//設置cookie
    	document.cookie = "userId=nick123" 
    	//設置過期時間
    	document.cookie = "userId=nick123; expires=Wed, 15 Jan 2020 12:00:00 UTC"
        //設置所屬路徑,默認當前頁面路徑
    	document.cookie = "userId=nick123; expires=Wed, 15 Jan 2020 12:00:00 UTC; path=/user" 
    	//設置cookie域
    document.cookie = "userId=nick123; expires=Wed, 15 Jan 2020 12:00:00 UTC; path=/user; domain=mysite.com" 
    
    //讀取
    	//獲取所有cookie
    	const cookies = document.cookie 
    	//使用正則讀取指定名稱的cookie
        function getCookieValue(name) {
          let result = document.cookie.match("(^|[^;]+)\\s*" + name + "\\s*=\\s*([^;]+)")
          return result ? result.pop() : ""
        } 
    	//不使用正則讀取指定cookie
        function getCookieValue(name) {
          const nameString = name + "="
          const value = document.cookie.split(";").filter(item => {
            return item.includes(nameString)
          })
          if (value.length) {
            return value[0].substring(nameString.length, value[0].length)
          } else {
            return ""
          }
        }
    //修改
    	//已覆蓋的方式修改
    	document.cookie = "userId=new_value"
    //刪除
    	document.cookie = "userId=; expires=Thu, 01 Jan 1970 00:00:00 UTC;"
    
  • 使用npm庫

    npm i js-cookie -S
    
    import Cookies from 'js-cookie'
    //設置cookie
    Cookies.set('foo', 'bar')
    //設置過期時間
    Cookies.set('name', 'value', { expires: 7 })
    //設置所屬路徑
    Cookies.set('name', 'value', { expires: 7, path: '' })
    //讀取
    Cookies.get('name') 
    //讀取所有
    Cookies.get()
    //讀取所屬域下的cookie
    Cookies.get('foo', { domain: 'sub.example.com' }) 
    //刪除
    Cookies.remove('name')
    

Cookie的缺陷

  • Cookie 不夠大

    Cookie的大小限制在4KB左右,對於復雜的存儲需求來說是不夠用的。當 Cookie 超過 4KB 時,它將面臨被裁切的命運。這樣看來,Cookie 只能用來存取少量的信息。此外很多瀏覽器對一個站點的cookie個數也是有限制的。
    
    這里需注意:各瀏覽器的cookie每一個name=value的value值大概在4k,所以4k並不是一個域名下所有的cookie共享的,而是一個name的大小
    
  • 過多的 Cookie 會帶來巨大的性能浪費

    Cookie 是緊跟域名的。同一個域名下的所有請求,都會攜帶 Cookie。大家試想,如果我們此刻僅僅是請求一張圖片或者一個 CSS 文件,我們也要攜帶一個 Cookie 跑來跑去(關鍵是 Cookie 里存儲的信息並不需要),這是一件多么勞民傷財的事情。Cookie 雖然小,請求卻可以有很多,隨着請求的疊加,這樣的不必要的 Cookie 帶來的開銷將是無法想象的。
    
    cookie是用來維護用戶信息的,而域名(domain)下所有請求都會攜帶cookie,但對於靜態文件的請求,攜帶cookie信息根本沒有用,此時可以通過cdn(存儲靜態文件的)的域名和主站的域名分開來解決
    
  • 由於在HTTP請求中的Cookie是明文傳遞的,所以安全性成問題,除非用HTTPS

Cookie與安全

屬性 作用
value 如果用於保存用戶登錄狀態,應該要將該字段加密,不能使用明文的用戶標識
http-only 不能通過js訪問Cookie,減少XSS攻擊
secure 只能在協議為https的請求中攜帶
same-site 規定瀏覽器不能在跨域請求中攜帶Cookie,減少CSRF攻擊

LocalStorage

特點

  • 保存的數據長期存在(直到清除瀏覽器的緩存),下一次訪問該網站的時候,網頁可以直接讀取以前保存的數據
  • 大小為5M左右
  • 僅在客戶端使用,不和服務端進行通信
  • 接口封裝較好

使用場景

LocalStorage可以作為瀏覽器本地緩存方案,用來提升網頁首屏渲染速度(根據第一請求返回時,將一些不變信息直接存儲在本地)

讀寫操作

localStorage.setItem(key,value)  保存數據
localStorage.getItem(key)        獲取數據
localStorage.removeItem(key)     刪除數據
localStorage.clear();            刪除全部數據

sessionStorage

簡介

sessionStorage保存的數據用於瀏覽器的一次會話,當會話結束(通常是該窗口關閉),數據被清空;sessionStorage 特別的一點在於,即便是相同域名下的兩個頁面,只要它們不在同一個瀏覽器窗口中打開,那么它們的 sessionStorage 內容便無法共享;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。除了保存期限的長短不同,SessionStorage的屬性和方法與LocalStorage完全一樣

特點

  • 會話級別的瀏覽器存儲
  • 大小為5M左右
  • 僅在客戶端使用,不和服務端進行通信
  • 接口封裝較好

使用場景

有效對表單信息進行維護,比如刷新時,表單信息不丟失

讀寫操作

sessionStorage.setItem(key,value)  保存數據
sessionStorage.getItem(key)        獲取數據
sessionStorage.removeItem(key)     刪除數據
sessionStorage.clear();            刪除全部數據
  • 共同點
  • 都是保存在瀏覽器端,且都遵循同源策略
  • 只能存儲字符串
  • 不同點
  • 生命周期

    • localStorage 是持久化的本地存儲,存儲在其中的數據是永遠不會過期的,使其消失的唯一辦法是手動刪除
    • sessionStorage 是臨時性的本地存儲,它是會話級別的存儲,當會話結束(頁面被關閉)時,存儲內容也隨之被釋放
  • 作用域

    • localStorage只要在相同的協議、相同的主機名、相同的端口下,就能讀取/修改到同一份localStorage數據
    • sessionStorage比localStorage更嚴苛一點,除了協議、主機名、端口外,還要求在同一窗口(當前同一個源下面的只要有一個窗口沒關或者跳到另外的窗口,sessionStorage都會存在)下

Web Storage 是一個從定義到使用都非常簡單的東西,它使用鍵值對的形式進行存儲,這種模式有點類似於對象,卻甚至連對象都不是——它只能存儲字符串,要想得到對象,我們還需要先對字符串進行一輪解析。Web Storage 是對 Cookie 的拓展,它只能用於存儲少量的簡單數據。當遇到大規模的、結構復雜的數據時,Web Storage 也愛莫能助了。這時候我們就要清楚我們的終極大 boss——IndexedDB

IndexedDB

簡介

indexedDB是一個運行在瀏覽器上的非關系型數據庫,沒有存儲上線,一般不會小於250M,它不僅可以儲存字符串,還可以儲存二進制數據。

IndexedDB的特點

  • 鍵值對存儲
IndexedDB 內部采用對象倉庫(object store)存放數據。所有類型的數據都可以直接存入,包括 JavaScript 對象。對象倉庫中,數據以"鍵值對"的形式保存,每一個數據記錄都有對應的主鍵,主鍵是獨一無二的,不能有重復,否則會拋出一個錯誤
  • 異步
IndexedDB 操作時不會鎖死瀏覽器,用戶依然可以進行其他操作,這與 LocalStorage 形成對比,后者的操作是同步的。異步設計是為了防止大量數據的讀寫,拖慢網頁的表現
  • 支持事務
IndexedDB 支持事務(transaction),這意味着一系列操作步驟之中,只要有一步失敗,整個事務就都取消,數據庫回滾到事務發生之前的狀態,不存在只改寫一部分數據的情況。
  • 同源限制
IndexedDB 受到同源限制,每一個數據庫對應創建它的域名。網頁只能訪問自身域名下的數據庫,而不能訪問跨域的數據庫
  • 儲存空間大
IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少於 250MB,甚至沒有上限
  • 支持二進制儲存
IndexedDB 不僅可以儲存字符串,還可以儲存二進制數據(ArrayBuffer 對象和 Blob 對象)

IndexedDB的常見操作

  • 建立打開IndexedDB ----window.indexedDB.open("testDB")
function openDB(name) {
	var request = window.indexedDB.open(name) //建立打開IndexedDB
	console.log('request', request)
	request.onerror = function (e) {
		console.log('open indexdb error')
	}
	request.onsuccess = function (e) {
		myDB.db = e.target.result //這是一個 IDBDatabase對象,這就是IndexedDB對象
		console.log(myDB.db) //此處就可以獲取到db實例
	}
}
var myDB = {
	name: 'testDB',
	version: '1',
	db: null
}
    
openDB(myDB.name)
  • 關閉IndexedDB----indexdb.close()
function closeDB(db){
    db.close();
}
  • 刪除IndexedDB----window.indexedDB.deleteDatabase(indexdb)
function deleteDB(name) {
  indexedDB.deleteDatabase(name)
}

總結

  • Cookie 的本職工作並非本地存儲,而是“維持狀態”
  • Web Storage 是 HTML5 專門為瀏覽器存儲而提供的數據存儲機制,不與服務端發生通信
  • IndexedDB 用於客戶端存儲大量結構化數據

參考

https://www.jianshu.com/p/8e86bf912b0e

https://juejin.im/post/5d8c33cb5188255a12365056

https://github.com/js-cookie/js-cookie

https://github.com/ljianshu/Blog/issues/25


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM