概述
本文主要講述 Session + Storage + Cache-Control + ETag + Cookie 這五者的作用及區(qū)別
Session
首先通過代碼認識一下 Session悬荣。之前我們說 Cookie 可以存儲我們的一些信息顿涣,但是由于用戶在瀏覽器中可以對 Cookie 進行操作,顯然這不是我們想要的,所以 Session 應運而生,Session 解決了 Cookie 不安全的痛點
code
我們在內(nèi)存中開辟一個空間,用來存儲 Session
let sessions = {}
當用戶登錄成功時
let sessionId = Math.random() * 1000000
sessions[ sessionId ] = { key: value } // 表示存儲的用戶信息
response.setHeader( 'Set-Cookie', `sessionId = ${ sessionId }` ) // Cookie: 'sessionId = 隨機數(shù)'
當此用戶訪問首頁時失球,遍歷 Cookie,將所有 Cookie 存儲到一個 hash(哈希表)中帮毁,之后
let mySession = sessions[ hash.sessionId ]
let username
if( mySession ){
username = mySession.用戶信息 // 用戶信息表示 sessions 中的{ key: value }
}
Session 特點
- 服務器通過 Cookie(
sessionId = ${ sessionId }
) 將 SessionId(隨機數(shù))發(fā)給瀏覽器 - 服務器有一塊內(nèi)存保存了所有的 Session(哈希表)
- 當瀏覽器訪問服務器時实苞,服務器讀取 SessionId
- 服務器通過 SessionId 可以得到對應用戶的隱私信息
- 用戶每次登錄都會設置一個 SessionId,并且 SessionId 不保存在服務器中
Storage
作為 Web Storage API 的接口(HTML5)烈疚,Storage 提供了訪問特定域名下的會話存儲(session storage)和本地存儲(local storage)的功能黔牵,例如:增刪改查存儲的數(shù)據(jù)項。Storage 與 HTTP 無關胞得,它是瀏覽器上的哈希表荧止,Storage 文件存儲在本地的一個文件夾中
-
window.sessionStorage
==> 操作一個域名的會話存儲(session storage) -
window.localStorage
==> 操作一個域名的本地存儲(local storage)
API
Storage.setItem()
==> 接收一個鍵名和值作為參數(shù)屹电,把鍵值對添加到存儲中,如果鍵名存在跃巡,則更新其對應的值Storage.getItem()
==> 接收一個鍵名作為參數(shù)危号,返回鍵名對應的值Storage.removeItem()
==> 接收一個鍵名作為參數(shù),并把該鍵名從存儲中刪除Storage.clear()
==> 清空存儲中的所有鍵名
對象的存儲
localStorage.setItem( 'object', { name: 'obj' } ) // object [ object Object ]
瀏覽器會將
{ name: 'obj' }
轉化為字符串即 ({ name: 'obj' }).toString
素邪,所以當我們存儲對象時外莲,使用 JSON ,即
localStorage.setItem( 'object', JSON.stringify({ name: 'obj' }))
localStorage
使用場景
記錄是否提示過用戶 + 記錄一些不敏感的信息兔朦,常見新手引導界面
let already = localStorage.getItem( 'isGuide' )
if( !already ){
// 開啟引導
localStorage.setItem( 'isGuide', true )
}
特點
- localStorage 與 HTTP 無關偷线,所以 HTTP 不會帶上 localStorage 的值
- 每個域名的 localStorage 有最大存儲量,因瀏覽器而異
- 只有相同域名的頁面才能互相讀取 localStorage
- localStorage 永久有效沽甥,除非用戶清除
sessionStorage
特點
- sessionStorage 與 HTTP 無關声邦,所以 HTTP 不會帶上 sessionStorage 的值
- 每個域名的 sessionStorage 有最大存儲量,因瀏覽器而異
- SessionStorage 只在同一瀏覽器窗口中共享
- sessionStorage 在用戶關閉頁面后就會失效
Cache-Control
Cache-Control 通用消息頭被用于在 HTTP 請求和響應中通過指定指令來實現(xiàn)緩存機制摆舟。當我們請求的文件(css亥曹、js)很大時,可以使用 Cache-Control 實現(xiàn)緩存恨诱,從而達到性能優(yōu)化的目的
前提:使用相同的 URL 才能實現(xiàn) Cache-Control 緩存機制
HTML
<link rel = "stylesheet" href = "URL">
<script src = "URL">
后端 + code
else if( path === '/js/main.js' ){
response.setHeader( 'Cache-Control', 'max-age = 30' )
// 30s 內(nèi)如果請求 main.js 文件媳瞪,瀏覽器不發(fā)送請求,直接使用緩存中文件 ==> 下載時間 === 0
}
特點
- 讓瀏覽器在一段時間內(nèi)不訪問服務器照宝,不發(fā)送請求蛇受,直接使用本地硬盤 | 內(nèi)存作為響應,從而減少請求時間
- 首頁(入口文件 + HTML)不設置 Cache-Control厕鹃,因為在緩存的這段時間內(nèi)兢仰,用戶不能獲取最新網(wǎng)頁
- 其他文件(css + js)會緩存很久(10年,甚至更久)熊响,如要更新旨别,只需要改變?nèi)肟谖募℉TML)的 URL 即可,之后瀏覽器就會緩存最新版的文件
-
URL 改變實現(xiàn)方式:+ 查詢參數(shù) | + 隨機數(shù)
Expires
Expires 頭指定了一個日期 | 時間汗茄, 在這個日期 | 時間之后,HTTP響應被認為是過時的
Cache-Control | Expires
從 Expires ==> Cache-Control 是 HTTP 升級的過程铭若,以前使用 Expires 加緩存洪碳,現(xiàn)在使用 Cache-Control 加緩存,Expires 的問題在于叼屠,它的過期時間是本地的時間瞳腌,如果本地時間錯亂,可能導致用戶一直不能使用緩存镜雨,從而影響用戶體驗
兩者的區(qū)別在于:Cache-Control 設置緩存時長嫂侍,Expires 設置緩存過期時間點。如果兩者同時設置,Cache-Control 優(yōu)先使用
ETag
ETag HTTP 響應頭是資源的特定版本的標識符挑宠》贫埽可以讓緩存更加高效并節(jié)省寬帶,如果內(nèi)容沒有改變各淀,Web 服務器不需要發(fā)送完整的響應
MD5
MD5 指摘要算法懒鉴,它可以把一個文件轉化成一個字符串。若文件內(nèi)容相同碎浇,則字符串相同临谱。文件內(nèi)容差異越小,字符串(算出來的結果)差異越大
后端 + code
安裝 MD5 npm install md5
奴璃,然后 node.js 使用 MD5
else if( path === '/js/main.js' ){
let string = fs.readFileSync( './js/main.js', 'utf-8' )
let fileMd5 = md5( string )
response.setHeader( 'ETag', fileMd5 ) // 響應頭中有 ETag ==> ETag: md5 值
// 當設置了 ETag 響應頭悉默,下次刷新時,請求中會多一個 If-None-Match 的請求頭苟穆,值為 ETag 的值(md5 值)
if( request.header[ 'if-none-match' ] === fileMd5 ){ // 如果請求的版本號(md5 值) === 瀏覽器的 If-None-Match 的值(md5 值) ==> 相同版本不需要下載
// 沒有響應體
response.statusCode = 304
// 304 Not Modified 表示資源未被修改麦牺,因為請求頭指定的版本If-Modified-Since或If-None-Match。在這種情況下鞭缭,由于客戶端仍然具有以前下載的副本剖膳,因此不需要重新傳輸資源。
} else{
response.statusCode = 200
// 有響應體
response.write( string )
}
response.end()
}
緩存機制
Cache-Control + ETag 聯(lián)合使用
辨析
Cookie + Session
- Cookie 指某些服務器在瀏覽器終端的一些數(shù)據(jù)(通常經(jīng)過加密)岭辣,一般為了辨別用戶身份吱晒,也可以儲存少量信息
- Session 是指服務器通過某種方式確定了用戶身份后的會話狀態(tài),一般表現(xiàn)為服務器為每個用戶單獨存儲的一部分數(shù)據(jù)
- Session 是基于 Cookie 實現(xiàn)的沦童,Cookie 是 Session 的基石
- Cookie 存儲在瀏覽器本地仑濒,用戶可以看到內(nèi)容。Session 存儲在服務器偷遗,用戶無法查看內(nèi)容墩瞳,一般 Session 的內(nèi)容是進程\線程間共享的
- Cookie 不安全,而 Session 解決了 Cookie 不安全的痛點
Cookie + Storage
- Cookie 和 Storage 都存儲在本地的一個文件中
- 兩者都可以做跨頁面通信氏豌,兩者都不能跨域訪問
- Cookie 的每次請求相同域名時喉酌,都會帶上 Cookie 里的所有內(nèi)容去訪問服務器
- Storage 與 HTTP 無關,不會被帶給服務器
- Cookie 在做跨頁面通信時泵喘,由于帶上所有內(nèi)容泪电,導致上傳數(shù)據(jù) + 請求變慢,Storage 的出現(xiàn)解決了 Cookie 的痛點纪铺,只要將一些不敏感信息存儲在 Storage 中即可
- JS 調用 Cookie 比較麻煩相速,一般都用庫進行封裝。Storage 調用起來比較簡單鲜锚,也可以再次封裝達到更好的效果
- Cookie 大小 4K 左右突诬,Storage 大小 5M 左右
- 后臺代碼可以任意設置 Cookie 的過期時間苫拍。Storage 中的 LocalStorage 永久有效,除非用戶刪除旺隙,Storage 中的 SessionStorage 在用戶關閉頁面(Session 結束)后就失效
LocalStorage + SessionStorage
- 兩者與 HTTP 無關
- 每個域名的 LocalStorage | sessionStorage 有最大存儲量绒极,因瀏覽器而異
- 只有相同域名的頁面才能互相讀取 LocalStorage。SessionStorage 只在同一瀏覽器窗口中共享
- LocalStorage 本地存儲催束, SessionStorage 會話存儲
- LocalStorage 永久有效集峦,除非用戶刪除。SessionStorage 在用戶關閉頁面(Session 結束)后就失效
Cache-Control + ETag
- 兩者都是 HTTP 響應頭抠刺,都可以實現(xiàn)加快請求 | 響應速度
- Cache-Control 是直接使用本地緩存塔淤,不會發(fā)送請求
- ETag 發(fā)送請求,如果 MD5 值相同速妖,則沒有響應體