近段時(shí)間都是在更新前端學(xué)習(xí)相關(guān)的文章,今天來學(xué)習(xí)和總結(jié)一下一個(gè)web通用知識: 瀏覽器緩存,Cookie和Session。這玩意對前端的性能優(yōu)化也有一定作用,應(yīng)該屬于前端必須掌握的知識之一了。 緩存在說這些之前,先說說瀏覽器的緩存。為什么會(huì)出現(xiàn)瀏覽器的緩存技術(shù)?不想下東西唄。同樣的東西,我每次請求都要下一次,不管是從用戶體驗(yàn)還是速度的方面考慮,都非常的僵硬。于是聰明的前端——哦不,瀏覽器設(shè)計(jì)者就想到了增加緩存這個(gè)東西。 前端想要自己控制緩存,可以在header上設(shè)置cache control(Link至MDN,以下部分內(nèi)容來自MDN)。不算非標(biāo)準(zhǔn)的拓展命令,可以使用的屬性值為以下: 緩存請求指令:
緩存響應(yīng)指令:
一個(gè)個(gè)說的話就太麻煩了,還是直接看MDN比較好。這里我畫一個(gè)簡單的思維導(dǎo)圖做輔助記憶用。 http://image109.360doc.com/DownloadImg/2017/09/0816/110402526_1_20170908045436225.jpg ![]() Cache-control
看圖細(xì)心的話應(yīng)該能夠發(fā)現(xiàn),圖中有一個(gè)s-maxage,對它的設(shè)置會(huì)覆蓋maxage和Expire。Expire是什么?這就是我們能夠在Header中設(shè)置的另外一個(gè)值。將Expires-cache contrl設(shè)置為一個(gè)時(shí)間,那么只要當(dāng)前時(shí)間沒有到這個(gè)時(shí)間,我們所有對服務(wù)器進(jìn)行的請求都將不被接受轉(zhuǎn)而直接走硬盤。(Expire的解釋在MDN上沒有中文,我認(rèn)為應(yīng)該直接翻譯為“過期時(shí)間”?) 但是Expire有一個(gè)小小的問題,就是這個(gè)時(shí)間怎么來。要知道,瀏覽器的取時(shí)間方法(比如getTime)都是直接取得系統(tǒng)時(shí)間,這樣就帶來一個(gè)問題。根據(jù)客戶端信息不可靠原則,如果我本地的時(shí)間錯(cuò)亂(比如我這種裝了雙系統(tǒng)然后Linux每次都會(huì)莫名改寫windows時(shí)間的),那么Expire就形同虛設(shè)。所以嘛,一般不推薦使用Expire. 我們還能夠設(shè)置的一個(gè)屬性則是Last-Modified。如果設(shè)置了Last-Modified,那么它將默認(rèn)保存緩存的內(nèi)容300S。 CookieCookie是啥我想我就不需要解釋了,最簡單的Cookie設(shè)置方法就是document.cookie/Cookies.set方法。在Set Cookies以后,對相同域名的所有請求都會(huì)帶上這個(gè)Cookie回傳。Cookie一般分為兩種類型,分別為非持久Cookie(內(nèi)存Cookie)和持久Cookie(硬盤Cookie)。內(nèi)存Cookie由瀏覽器維護(hù),保存在內(nèi)存中,瀏覽器關(guān)閉后就消失了,而硬盤Cookie則有一個(gè)過期時(shí)間,過期時(shí)間內(nèi)是持續(xù)有效的。 為什么要有Cookie? 因?yàn)镠TTP協(xié)議是無狀態(tài)的,服務(wù)器無法記錄用戶上一次的操作,這樣就造成了交互上的阻礙。而Cookie就可以做到繞開HTTP的無狀態(tài)。服務(wù)器借由從Cookie中讀取包含的信息,借以維護(hù)用戶和服務(wù)器會(huì)話中的狀態(tài)。(比如購物/登錄)。 Cookie的路徑Cookie一般都是由于用戶訪問一個(gè)頁面才產(chǎn)生的,但是我們會(huì)遇到一個(gè)問題——并不是只有在創(chuàng)建Cookie的頁面才需要訪問這個(gè)Cookie。如果出于安全考慮,只有與創(chuàng)建Cookie的頁面出于同一個(gè)目錄或在創(chuàng)建Cookie頁面的子目錄下的網(wǎng)頁才可以訪問。 那么這樣就又會(huì)帶來一個(gè)問題:如果者說我希望其父級乃至整個(gè)網(wǎng)頁都能夠使用Cookie,怎么做呢? 可以這樣: document.cookie="userName=CoderMageFox;path=/"; Cookie的域路徑問題解決了,又一個(gè)問題擺在了面前。如果我們在同一個(gè)主域下有不同的域名(如img.codermagefox.com和test.codermagefox.com)那么如何互相訪問呢?要知道,這個(gè)需求的場景相當(dāng)多。這個(gè)時(shí)候,我們可以選擇指定可訪問Cookie的主機(jī)名來進(jìn)行設(shè)置。 document.cookie="name=codermagefox;domain=codermagefox.com path=/;" 這樣就可以解決啦。 Cookie的缺陷
然而我在翻閱《JavaScript權(quán)威指南》的時(shí)候發(fā)現(xiàn)了一點(diǎn),現(xiàn)代瀏覽器遵循的HTTP標(biāo)準(zhǔn)是RFC2965。 書上原文: ![]() 而這個(gè)標(biāo)準(zhǔn)中對于這一段是這么寫的:
看到這里我有點(diǎn)懵逼了。不是說at least 嗎?所以說這些標(biāo)準(zhǔn)其實(shí)是瀏覽器自己定的而不是文檔規(guī)定的?這個(gè)坑我暫時(shí)沒弄明白,以后弄明白了再回來填。 Session正如同上面所說,HTTP的傳輸有一個(gè)很大的問題,就是明文傳輸。明文傳輸會(huì)導(dǎo)致一個(gè)什么問題?我可以抓包來獲取很多用戶信息(比如使用WireShark\Fiddle等工具)而且HTTP請求是可以篡改的,并且十分容易篡改。又根據(jù)客戶端信息不可靠原則,我們需要一個(gè)東西來驗(yàn)證用戶的身份怎么辦呢? 這個(gè)時(shí)候,Session就出馬了。Session也可以做到Cookie的部分功能,不過,Session是保存在服務(wù)器上的。服務(wù)端的信息無法隨便篡改,所以Session可以做到可靠。具體的做法一般是服務(wù)端和客戶端之間不傳輸明文數(shù)據(jù),而是傳輸一段經(jīng)過特殊加密的密文,密文對應(yīng)的服務(wù)器硬盤數(shù)據(jù)中才是真實(shí)的數(shù)據(jù)。這段數(shù)據(jù)在Session激活后從服務(wù)器磁盤中取出到內(nèi)存中,再返回給瀏覽器。 需要注意的是,Session是一種抽象的概念,開發(fā)者為了實(shí)現(xiàn)中斷和繼續(xù)等操作,將 user agent 和 server 之間一對一的交互,抽象為“會(huì)話”,進(jìn)而衍生出“會(huì)話狀態(tài)”。而而 cookie 是一個(gè)實(shí)際存在的東西,http 協(xié)議中定義在 header 中的字段。Session可以被認(rèn)為是一種Cookie的后端無狀態(tài)實(shí)現(xiàn)。 當(dāng)然,現(xiàn)在很多大流量的網(wǎng)站使用的一般是Secret Cookie,這又是另外一種做法了。 便于記憶的思維導(dǎo)圖: ![]() 寫了這么多,對于Cookie/Session的理解算是有一些了。今天收獲不錯(cuò),Nice! |
|