你真的懂HTTP緩存嗎?
共 5410字,需瀏覽 11分鐘
·
2024-05-24 12:10
作者:程序員小楊v1
鏈接:https://juejin.cn/post/7281088405189427215
背景
需求開發(fā)中不斷的往項目中添加圖片、字體等這些靜態(tài)資源使得項目打包體積越來越大。
打包后這些靜態(tài)資源占據(jù)了包體積的大部分。
基于此,我們準(zhǔn)備將靜態(tài)資源從項目中移出來放到 oss 云服務(wù)上,這樣項目的體積會縮小很多,打包速度也會快很多
但是,想法是好的,但是具體的操作上存在一些問題需要解決:
-
靜態(tài)資源的緩存問題 -
目錄結(jié)構(gòu)問題 -
資源更新問題
這篇文章我會重點分享靜態(tài)資源緩存問題的解決方案。
HTTP 緩存
說到靜態(tài)資源的緩存問題其實就是HTTP緩存的問題,我們既要保證客戶端能快速的加載靜態(tài)資源還需要保證當(dāng)靜態(tài)資源變化時,客戶端能及時更新。
緩存過程
由上圖我們可以發(fā)現(xiàn):
-
瀏覽器在請求資源時,都會去查看當(dāng)前瀏覽器緩存中是否存在緩存結(jié)果和緩存標(biāo)識 -
當(dāng)請求結(jié)果返回瀏覽器時,瀏覽器都會將當(dāng)前結(jié)果和緩存標(biāo)識存入瀏覽器緩存中
以上兩點是瀏覽器緩存機制的關(guān)鍵,它確保了每個請求的緩存存入與讀取。
根據(jù)是否需要向服務(wù)器重新發(fā)起 HTTP 請求將緩存過程分為兩個部分,分別是強緩存和協(xié)商緩存。
強緩存
強緩存,顧名思義就是強制緩存,是不需要向原服務(wù)器發(fā)起請求直接使用瀏覽器緩存
強緩存的實現(xiàn)方案主要是有兩種:Expires 和 cache-control
-
Expires:過期時間,如果設(shè)置了過期時間,則瀏覽器會在過期時間內(nèi)使用緩存。Expires 是 HTTP1.0 的產(chǎn)物,受限于本地時間,如果人為修改了本地時間,可能會造成緩存失效。 -
cache-control:緩存控制,常用有以下幾個設(shè)置: -
max-age:表示緩存可以使用多長時間,是一個相對時間 -
public:表示響應(yīng)可以被任何區(qū)緩存 -
private:只針對個人用戶,不可被代理服務(wù)器緩存 -
no-cache:可以在本地緩存,可以在代理服務(wù)器緩存,但是這個緩存要服務(wù)器驗證才可以使用,強制客戶端總是向服務(wù)器發(fā)送請求,由服務(wù)器判斷緩存是否可用,即總是啟用協(xié)商緩存 -
no-store:徹底禁用緩存,每次都需要從服務(wù)器獲取資源,流量消耗增加
Expires 和 cache-control 都可以實現(xiàn)強緩存
資源在 2023 年 2 月 28 號 22:22:22 過期
Expires: Tue, 28 Feb 2023 22:22:22 GMT
資源在1小時內(nèi)可使用緩存
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600
但是Expires 是http1.0的產(chǎn)物,cache-control是http1.1的產(chǎn)物,現(xiàn)階段,我們會認(rèn)為cache-control使用更廣泛,Expires只是一種降級方案。
當(dāng)Expires 和 cache-control同時存在時,瀏覽器會優(yōu)先使用cache-control。
協(xié)商緩存
-
Etag/If-None-Match: -
Etag:這個字段是由服務(wù)器生成返回給瀏覽器的,它的值是由文件的索引節(jié)點(INode)、文件大小(size)、文件最后修改時間(MTime)進(jìn)行hash之后得到的 -
If-None-Match:再次請求該資源時,帶上上一次服務(wù)器返回的ETag值
過程:當(dāng)強緩存過期,瀏覽器會啟用協(xié)商緩存,首先判斷當(dāng)前是否存在ETag,如果存在,則再次向服務(wù)器發(fā)送請求時,在請求頭上加上If-None-Match一同發(fā)送到服務(wù)器,服務(wù)器比對當(dāng)前的If-None-Match與資源相對應(yīng)的ETag是否相同,如果相同則說明緩存可用,則返回304,否則返回最新的資源。
-
Last-Modified/If-Modified-Since: -
Last-Modified:服務(wù)器返回的文件最后修改時間 -
If-Modified-Since:再次請求資源是,帶上上一次服務(wù)器返回的Last-Modified值
過程:當(dāng)資源過期時,如果不存在ETag而是存在Last-modified,則再次向服務(wù)器發(fā)送請求時,在請求頭上會帶上If-Modified-Since一同發(fā)送給服務(wù)器,服務(wù)器對比資源最后修改時間和當(dāng)前客戶端發(fā)送的If-Modified-Since這個時間,判斷資源是否被修改,如果修改了則返回最新的資源,如果沒有修改則返回304,使用緩存。微信搜索公眾號:架構(gòu)師指南,回復(fù):架構(gòu)師 領(lǐng)取資料 。
ETag的優(yōu)先級高于Last-Modified,服務(wù)器會優(yōu)先驗證ETag
Last-Modified是以秒為單位的,所以在資源頻繁更改的情況下,Last-Modified是不安全的,而ETag可以檢查文件大小和文件的唯一索引節(jié)點,故即使修改頻繁的資源依然能檢測到更改
緩存策略
基于上面介紹的強緩存和協(xié)商緩存特點,以下是筆者總結(jié)的緩存策略;
頻繁變動的資源
對于頻繁變動的資源,肯定首先要保證的就是及時性,即服務(wù)器文件更新,需要盡快展示在客戶端,所以對于此種資源,建議禁用強制緩存,采用協(xié)商緩存的策略。
cache-control: no-cache
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
ETag: deadbeef
以上標(biāo)識中
-
cache-control: no-cache ,表示每次都從服務(wù)器詢問資源是否更改 -
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT, 表示資源的最后修改時間 -
ETag: deadbeef ,表示資源對應(yīng)的唯一標(biāo)識
過程如下:
-
當(dāng)瀏覽器查發(fā)現(xiàn)
cache-control: no-cache時,會向服務(wù)器發(fā)起該資源的請求 -
但是在請求前,瀏覽器會先在自己的緩存中查找該資源, 如果發(fā)現(xiàn)存在該資源的緩存文件,則將該緩存文件的
Etag和Last-Modified字段轉(zhuǎn)換為請求頭中的If-None-Match和If-Modified-Since一同發(fā)送到服務(wù)端 -
如果發(fā)現(xiàn)不存在該資源,則直接請求
-
服務(wù)器接收到資源請求,如果不存在
If-None-Match和If-Modified-Since請求頭,則說明客戶端沒有緩存,直接返回資源 -
如果存在
If-None-Match和If-Modified-Since請求頭,服務(wù)器比對當(dāng)前的If-None-Match與資源相對應(yīng)的ETag是否相同,如果相同則說明文件沒有更改,返回304讓瀏覽器使用緩存,如果不相同,返回新文件。
不經(jīng)常變化的資源
對于不經(jīng)常變化的資源,建議設(shè)置強緩存,
cache-control:max-age=31536000
如上設(shè)置會強緩存該資源一年時間,如果我們中間需要修改該資源,可以采用在資源鏈接末尾添加唯一hash或是唯一時間戳來解決。
加餐
對于需要緩存的文件,建議明確指出cache-control字段,如果沒有設(shè)置該字段,則瀏覽器會采用一種叫做啟發(fā)式緩存的方式緩存文件。
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT
如果存在以上響應(yīng),不存在cache-control字段
試探性地知道,整整一年沒有更新的內(nèi)容在那之后的一段時間內(nèi)不會更新。
因此,客戶端存儲此響應(yīng)(盡管缺少 max-age)并重用它一段時間。
復(fù)用多長時間取決于實現(xiàn),但規(guī)范建議存儲后大約 10%(在本例中為 0.1 年)的時間。
由此可見,如果不指明cache-control字段會導(dǎo)致不必要的緩存,或是無謂的流量消耗。
所以,建議所有靜態(tài)資源都明確指出cache-control字段,明確緩存策略。
— 完 —
關(guān)注公眾號后,回復(fù)下面關(guān)鍵詞獲取
回復(fù) 加群,加入前端程序員技術(shù)交流群
回復(fù) 面試,獲取最新大廠面試資料
回復(fù) 簡歷,獲取 3200 套 簡歷模板
回復(fù) TypeScript,獲取 TypeScript 精講課程
回復(fù) uniapp,獲取 uniapp 精講課程
回復(fù) Node,獲取 Nodejs+koa2 實戰(zhàn)教程
回復(fù) 架構(gòu)師,獲取 架構(gòu)師學(xué)習(xí)資源教程
更多教程資源應(yīng)用盡有,歡迎 關(guān)注獲取
“分享、點贊、在看” 支持一波??
