緩存對于一個(gè)網(wǎng)站來說非常重要蕾管,可以提高網(wǎng)站性能齿拂,減少冗余的數(shù)據(jù)傳輸召调,增加服務(wù)器負(fù)擔(dān),web存儲則給瀏覽器提供了更加強(qiáng)大的保存文件的接口创葡。
有相當(dāng)一段時(shí)間一直混淆了HTTP緩存相關(guān)的屬性浙踢,HTML5離線存儲和本地儲存的一些關(guān)系绢慢,最近好好地整理了一下這些Web存儲相關(guān)的東西
先列出一些相關(guān)屬性和概念灿渴,看看能否理清它們之間的區(qū)別和聯(lián)系?
- manifest
- cache-control
- expires
- 304(no modified)
- ETag
- If-None-Match
- Last-Modified
- If-Modified-Since
- http-equiv
- webstorage
- cookie/session
是不是感覺有點(diǎn)凌亂胰舆,那就跟著我整理的筆記走一遍吧:)
首先說一說HTTP緩存相關(guān)的東西:
Cache-Control:
每一個(gè)用HTTP請求的資源都可以在響應(yīng)頭用Cache-Control來給瀏覽器定義緩存策略骚露,通過設(shè)置一些屬性值它可以控制誰可以,在什么條件下可以緩存響應(yīng)缚窿,還有緩存的有效期棘幸,這個(gè)屬性的一些常用值如下:
no-cache:
表示不使用緩存,先和服務(wù)器確認(rèn)要返回的資源是否有修改
no-store:
表示禁止瀏覽器和所有中繼緩存響應(yīng)的資源
max-age=100:
表示緩存的有效期倦零,單位是秒误续,這一段時(shí)間內(nèi)吨悍,除非緩存文件發(fā)生一些變動,否則會直接使用之前的緩存蹋嵌,注意這段時(shí)間內(nèi)是不會發(fā)Etag等方法去驗(yàn)證的資源有沒有修改的育瓜。緩存的文件發(fā)生變動,主要有這些情況:資源名更改栽烂,資源地址更改躏仇,緩存被刪除,網(wǎng)頁強(qiáng)制刷新等腺办;
資源名更改焰手,給文件名添加版本hash值,比如給image.png修改為image-hash.png怀喉,可以保證每次更新文件時(shí)用戶可以重新發(fā)出請求书妻,獲取最新的資源。資源路徑更改磺送,修改文件的請求路徑驻子,比如給image.png添加查詢參數(shù)修改為image.png?hash,max-age的時(shí)間設(shè)置根據(jù)每個(gè)網(wǎng)站的實(shí)際情況不同去設(shè)置估灿,一種極端的做法是把這個(gè)值設(shè)置很大崇呵,然后通過修改資源名或者給資源請求地址添加查詢參數(shù),來告訴瀏覽器該更新資源了馅袁,一般用在很久才更新網(wǎng)站的情況.
public:
用max-age即是默認(rèn)public了域慷,不用設(shè)置
private:
私人緩存,中繼緩存不被允許汗销,但是可以在瀏覽器緩存
HTTP緩存的其他概念:
expires:
表示存在的時(shí)間犹褒,使客戶端在這個(gè)設(shè)置的時(shí)間之前不用去請求資源,類似于max-age弛针,但是expires表示的是一個(gè)固定時(shí)間叠骑,而且可能有服務(wù)器和客戶端時(shí)間不一致的問題,主要用于HTTP1.0版本削茁,在HTTP1.1版本完全可以用功能更強(qiáng)的Cache-Control來替代宙枷,和max-age同時(shí)存在時(shí)expiers會被覆蓋掉
http-equiv:
緩存有兩種控制機(jī)制,一種是請求頭信息控制茧跋,另外一種就是利用meta標(biāo)簽慰丛;可以在HTML文檔中為meta標(biāo)簽設(shè)置http-equiv為相應(yīng)屬性名,content為值來設(shè)置緩存瘾杭,例如
<meta http-equiv="Expires" content="Mon, 20 Jul 2009 23:00:00 GMT" />
不過只對改網(wǎng)頁的HTML文件有緩存作用诅病,對該頁面的其他資源以及其他頁面的HTML文件都沒有作用
那么max-age(expires)到期之后,在no-cache下的資源會先和服務(wù)器確認(rèn)返回的資源是否有修改,如何實(shí)現(xiàn)這一過程贤笆?這就要用到
ETag/If-None-Match蝇棉,Last-Modified/If-Modified-Since
ETag (Entity Tag)其實(shí)就是一個(gè)驗(yàn)證令牌,用來標(biāo)識一個(gè)資源芥永,可能是一個(gè)hash值银萍,也可能是一個(gè)版本號,每當(dāng)資源有修改的時(shí)候ETag的值就會改變?yōu)g覽器第一次請求之后會保存響應(yīng)頭的ETag值恤左,以便下一次發(fā)送請求的時(shí)候校驗(yàn)Etag是否有更改贴唇。
那么下一次瀏覽器如何告訴服務(wù)器本地已經(jīng)存有Etag和相應(yīng)的資源了呢?
If-None-Match
通過在請求頭添加If-None-Match(如果存在ETag飞袋,瀏覽器會自動添加)戳气,賦值為上一次請求后在本地存儲的Etag值,服務(wù)器會和服務(wù)端最新資源的Etag比對巧鸭,如果沒有更改會直接返回304 no modified給瀏覽器瓶您,瀏覽器就直接使用本地緩存的文件
Last-Modified/If-Modified-Since
其作用等同于ETag/If-None-Match,
不過前者是通過規(guī)定一個(gè)時(shí)間來比對纲仍,最小的單位是秒呀袱,后者通過一個(gè)唯一標(biāo)識符,所以可以看出來如果原站在一秒內(nèi)有多次更新郑叠,那么前者就不頂用啦夜赵。
ETag的驗(yàn)證要優(yōu)先于Last-Modified,此外ETag也是有缺點(diǎn)的乡革,在分布式的環(huán)境中寇僧,Etag在不同服務(wù)器上的同步問題可能會給服務(wù)器帶來一些壓力。
HTTP緩存是和每一個(gè)HTTP請求直接相關(guān)的沸版,每一個(gè)請求資源的響應(yīng)都有相應(yīng)的緩存策略嘁傀,它們往往是相似的,是否可以通過其他的機(jī)制视粮,直接告訴瀏覽器去緩存哪一些文件呢细办?
HTML5離線存儲閃亮出場
H5離線存儲:服務(wù)器通過一份.manifest文件給瀏覽器提供一份完備的緩存名單,名單包括需要緩存的文件蕾殴,不需要緩存的文件的列表之外笑撞,還有一些其他的功能,比如給資源設(shè)置備選的請求地址区宇,設(shè)置404頁面等
實(shí)現(xiàn):利用H5的標(biāo)簽新屬性manifest娃殖,只需要在HTML文件添加
<html manifest="test.manifest">值戳,
服務(wù)器則將manifest文件的mime-type設(shè)置為text/cache-manifest類型即可议谷,瀏覽器每次請求會檢查manifest文件是否有更新,服務(wù)端通過修改manifest文件堕虹,即可在瀏覽器下一次請求資源的時(shí)候通知其更新相應(yīng)的資源卧晓。
作用:通過本地離線存儲可以在沒有網(wǎng)絡(luò)的情況下訪問網(wǎng)站事先保存的文件資源芬首,在有網(wǎng)絡(luò)的情況下直接使用本地資源也可以減少請求連接的壓力,提高網(wǎng)頁的加載速度逼裆,注意這里和HTTP緩存的區(qū)別郁稍,它是直接使用本地資源,請求返回的是200(from cache),由于有manifest來統(tǒng)一管理胜宇,所以不需要發(fā)請求查看是否有更新耀怜,也沒有過期時(shí)間。
PS:這里關(guān)于manifest文件自身的更新問題桐愉,還是要走HTTP緩存财破,或者直接不緩存這個(gè)文件。
前面提到的概念主要都是緩存請求文件這一塊的東西从诲,它們的目的都是為了提高網(wǎng)頁的性能左痢,可以說是一種優(yōu)化型的存儲,可以給用戶帶來更流暢的體驗(yàn)
但是我們印象中還有一種存儲系洛,它可以給我們提供更多的可能和效果的實(shí)現(xiàn)俊性,是功能型的存儲,如H5本地儲存Webstorage描扯,cookie定页,session
cookie,session
眾所周知绽诚,HTTP是無狀態(tài)的協(xié)議拯勉,每一次請求都是獨(dú)立沒有聯(lián)系的,瀏覽器和服務(wù)器都沒有辦法維持用戶的狀態(tài)憔购,判斷用戶是不是依然是之前的那個(gè)用戶宫峦。
很容易可以想到,在同一個(gè)用戶的每個(gè)請求頭添加一個(gè)唯一標(biāo)識符玫鸟,通過判斷這個(gè)標(biāo)識符就可以維持用戶的一些信息和狀態(tài)导绷。
會話信息被用來作為標(biāo)識符解決這個(gè)問題,cookie機(jī)制采用的是在客戶端保持狀態(tài)的方案屎飘,而session機(jī)制采用的是在服務(wù)器端保持狀態(tài)的方案(服務(wù)端保持狀態(tài)也需要客戶端保持狀態(tài)妥曲,所以一般session都要基礎(chǔ)cookie或者sessionstorage)
總的來說:cookie數(shù)據(jù)放在客戶端,session數(shù)據(jù)放在服務(wù)端钦购,cookie可以設(shè)置期限檐盟,session則是關(guān)閉瀏覽器時(shí)銷毀(cookie默認(rèn)也是),cookie不安全押桃,session可能會影響服務(wù)器性能
Cookie:通常用Javascript封裝一個(gè)setCookie的函數(shù)來創(chuàng)建葵萎,有大小限制,可能會導(dǎo)致請求頭過于臃腫,瀏覽器發(fā)送請求時(shí)羡忘,檢查本地cookie谎痢,如果該cookie聲明的范圍大于發(fā)送請求的url地址時(shí),就會自動在請求上添加cookie字段
session:服務(wù)器每次會檢查瀏覽器請求頭的session標(biāo)識卷雕,如果有則將這個(gè)session id在服務(wù)器的數(shù)據(jù)庫(散列表)查找节猿,找到后才進(jìn)行相應(yīng)權(quán)限的操作
如果沒有這個(gè)請求標(biāo)識,則為客戶端新建一個(gè)漫雕,返回給客戶端后滨嘱,客戶端可以通過cookie或者sessionstorage來保存這個(gè)session id,通過請求頭的cookie字段來給服務(wù)器提供sessionId浸间,當(dāng)cookie被禁止時(shí)就需要一些其他方法九孩,通常是采用添加到url路徑中,添加表單隱藏域等方法
cookie作為HTTP協(xié)議規(guī)范的一部分发框,主要還是用來儲存用戶信息的躺彬,用來和服務(wù)端交互,大小也有限制梅惯,僅僅只是一種會話級別的存儲
localstorage宪拥,sessionstorage
webstorage為了更大的存儲文件設(shè)計(jì),與Cookie負(fù)責(zé)記錄用戶信息相比铣减,webStorage專注于本地存儲她君,通過封裝好的setItem,getItem等方法即可使用
localstorage是一種持久化的存儲葫哗,除非主動刪除缔刹,否則永遠(yuǎn)存在,sessionstorage主要用來存儲會話(session)劣针,關(guān)閉瀏覽器就會銷毀校镐,是一種非持久化的存儲
除了上面這些的概念之外,還有諸如像IndexDB捺典,F(xiàn)ileSystem等存儲方法鸟廓,關(guān)于Web存儲的知識真的非常多,看上去坑也是不少襟己,還需要實(shí)踐慢慢來掌握引谜。