摘要:瀏覽器緩存只存在于每個多帶帶的客戶端,因此它是私有緩存。表示該資源既能被瀏覽器緩存,也能被任何中間人比如代理服務器等緩存。普通刷新會啟用協(xié)商緩存,忽略強緩存。只有在地址欄或收藏夾輸入網(wǎng)址通過鏈接引用資源等情況下,瀏覽器才會啟用強緩存。
前言
在訪問一個網(wǎng)頁時,客戶端會從服務器下載所需的資源。但是有些資源很少發(fā)生變動,例如 HTML、JS、CSS、圖片、字體文件等。如果每次加載頁面都從源服務器下載這些資源,不僅會增加獲取資源的時間,也會給服務器帶來一定壓力。因此,重用已獲取的資源十分重要。將請求的資源緩存下來,下次請求同一資源時,直接使用存儲的副本,而不會再去源服務器下載。這就是我們常說的緩存技術(shù)。
緩存的種類很多:瀏覽器緩存、網(wǎng)關(guān)緩存、CDN 緩存、代理服務器緩存等。這些緩存大致可以歸為兩類:共享緩存和私有緩存。共享緩存能夠被多個用戶使用,而私有緩存只能用于單個用戶。瀏覽器緩存只存在于每個多帶帶的客戶端,因此它是私有緩存。
本文主要介紹私有(瀏覽器)緩存。你將學習:
瀏覽器緩存的分類
如何啟用和禁止緩存
緩存存儲的位置
如何設(shè)置緩存的過期時間
緩存過期之后會發(fā)生什么
如何為自己的應用制定合適的緩存策略
調(diào)試
如何判斷網(wǎng)站是否啟用了緩存
如何禁用瀏覽器緩存
緩存存儲 啟用緩存 Cache-Control瀏覽器會根據(jù) HTTP Response Headers 中的一些字段來決定是否要緩存該資源。通過設(shè)置 Response Headers 中的?Cache-Control?和?Expires?可以啟用緩存,這樣資源就會被緩存到客戶端。
Cache-Control?可以設(shè)置?private?、public 、max-age?、?no-cache?來啟用緩存。
Cache-Control: private/public Cache-Control: max-age=300 Cache-Control: no-cache
private?:表示該資源只能被瀏覽器緩存。
public?:表示該資源既能被瀏覽器緩存,也能被任何中間人(比如代理服務器、CDN 等)緩存。
max-age?:表示該資源能夠被緩存的最大時間。如果設(shè)置 max-age=0?,該資源仍然會被瀏覽器緩存,只不過立刻就過期了。
no-cache?:該資源會被緩存,但是立刻就過期了,因此需要先和服務器確認資源是否發(fā)生變化,只有當資源沒有變化時,該緩存才會被使用,否則需要從服務器下載。相當于?max-age=0?。
ExpiresExpires?標識了緩存的具體過期時間,來控制資源何時過期。通過設(shè)置?Expires?可以啟用緩存。不過需要注意 Expires 的值是格林威治時間(Greenwich Mean Time, GMT),不是本地時間。
Expires: Fri, 08 Mar 2029 08:05:59 GMT Expires: 0 // Expires: 0 仍然會啟用緩存,只不過緩存立刻過期。優(yōu)先級
既然 Cache-Control 和 Expires 都能夠啟用緩存,那么問題來了,如果同時設(shè)置?Cache-Control: max-age=600?和?Expires: 0?,那么瀏覽器應該如何緩存該資源呢?答案是只有?Cache-Control: max-age=600?生效。因為 Cache-Control 的優(yōu)先級高于?Expires,如果同時設(shè)置了 Cache-Control 和 Expires,以 Cache-Control 為準。
瀏覽器的默認行為設(shè)置 Cache-Control 之后,可以看到瀏覽器確實啟用了緩存(from disk cache)。如下所示:
Cache-Control:max-age=604800, must-revalidate, public
但是我發(fā)現(xiàn),即使 Response Header 中沒有設(shè)置 Cache-Control 和 Expires,瀏覽器仍然會緩存某些資源。這是為什么呢?
原來當 Response Header 中有 Last-Modified 但是沒有 Cache-Control 和 Expires 時,瀏覽器會用一套自己的算法來決定這個資源會被緩存多長時間。這是瀏覽器為了提升性能進行的優(yōu)化,每個瀏覽器的行為可能不一致,有些瀏覽器上甚至沒有這樣的優(yōu)化。因此,如果要啟用緩存,還是應該自己設(shè)置合適的 Cache-Control 和 Expires,不要依賴瀏覽器自身的緩存算法。當然,如果在調(diào)試時發(fā)現(xiàn)本應該更新的文件沒有更新,也別忘了看看是否被瀏覽器緩存了。
禁止緩存給?Cache-Control?設(shè)置?no-store?會禁止瀏覽器和中間人緩存該資源。在處理包含個人隱私數(shù)據(jù)或銀行業(yè)務數(shù)據(jù)的資源時很有用。
Cache-Control: no-store緩存目標對象
一般來說,瀏覽器緩存只能存儲?GET?響應,例如 HTML、JS、CSS、圖片等靜態(tài)資源。因為這些資源不經(jīng)常發(fā)生變化,所以緩存可以幫助提升獲取資源的速度。但是像一些 POST/DELETE 請求,這些請求基本上每一次都不一樣,因此也沒有什么緩存的價值。
緩存位置瀏覽器可以在內(nèi)存、硬盤中開辟一個空間用以保存請求資源的副本。我們經(jīng)常在 Dev Tools 里面看到?Memory Cache(內(nèi)存緩存)和 Disk Cache(硬盤緩存),指的就是緩存所在的位置。請求一個資源時,會按照優(yōu)先級(Service Worker ->?Memory Cache -> Disk Cache ->?Push Cache)依次查找緩存,如果命中則使用緩存,否則發(fā)起網(wǎng)絡(luò)請求。這里只介紹常用的 Memory Cache 和 Disk Cache。
200 from Memory Cache
表示不訪問服務器,直接從內(nèi)存中讀取緩存。因為緩存的資源保存在內(nèi)存中,所以讀取速度較快,但是關(guān)閉進程之后,緩存的資源也會隨之銷毀。一般來說,系統(tǒng)不會給內(nèi)存分配較大的容量,因此內(nèi)存緩存一般用于存儲小文件。同時,內(nèi)存緩存在有時效性要求的場景下也很有用(比如瀏覽器的隱私模式)。
200 from Disk Cache
表示不訪問服務器,直接從硬盤中讀取緩存。與內(nèi)存相比,硬盤的讀取速度較慢,但是硬盤緩存持續(xù)的時間更長,關(guān)閉進程之后,緩存的資源仍然存在。由于硬盤的容量較大,因此一般用于存儲大文件。
總的來說就是:
內(nèi)存緩存:讀取快、持續(xù)時間短、容量小
硬盤緩存:讀取慢、持續(xù)時間長、容量大
緩存分類瀏覽器緩存一般分為兩類:強緩存(也稱本地緩存)和協(xié)商緩存(也稱弱緩存)。判定過程如下:
瀏覽器發(fā)送請求前,會先去緩存里面查看是否命中強緩存,如果命中,則直接從緩存中讀取資源,不會發(fā)送請求到服務器。否則,進入下一步。
當強緩存沒有命中時,瀏覽器一定會向服務器發(fā)起請求。服務器會根據(jù) Request Header 中的一些字段來判斷是否命中協(xié)商緩存。如果命中,服務器會返回響應,但是不會攜帶任何響應實體,只是告訴瀏覽器可以直接從緩存中獲取這個資源。否則,進入下一步。
如果前兩步都沒有命中,則直接從服務器加載資源。
強緩存和協(xié)商緩存的共同點在于,如果命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源。而不同點在于,強緩存不發(fā)送請求到服務器,而協(xié)商緩存會發(fā)送請求到服務器以驗證資源是否過期。普通刷新會啟用協(xié)商緩存,忽略強緩存。只有在地址欄或收藏夾輸入網(wǎng)址、通過鏈接引用資源等情況下,瀏覽器才會啟用強緩存。
緩存過期策略當緩存過期之后,瀏覽器會向服務器發(fā)起 HTTP 請求,以確定資源是否發(fā)生了變化。如果資源未改變,那么瀏覽器會繼續(xù)使用本地的緩存資源;如果該資源已經(jīng)發(fā)生變化了,那么瀏覽器會刪除舊的緩存資源,并將新的資源緩存到本地。
過期時間Http Response Header 里面的?Cache-Control: max-age=xxx?和 Expires?都可以設(shè)置緩存的過期時間,但是它們有一些區(qū)別:
Expires?:標識該資源過期的時間點,它是一個絕對值,即在這個時間點之后,緩存的資源過期。
max-age?:標識該資源能夠被緩存的最大的時間。它是一個相對值,相對于第一次請求該文檔時服務器記錄的「請求發(fā)起時間」。
雖然 Cache-Control?是 HTTP 1.1 提出來的新特性,但并不是說 max-age 優(yōu)于 Expires。它們都有各自的使用場景,我們應該根據(jù)業(yè)務需求去決定使用哪一個。比如當某個資源需要在特定的時間點過期時應該使用 Expires?。如果只是為了開啟緩存,使用 max-age?可能會更好些,因為 Cache-Control?的優(yōu)先級高于 Expires。
針對應用中幾乎不會改變的文件,通常可以設(shè)置一個較長的過期時間,以保證緩存的有效。例如圖片、CSS、JS 等靜態(tài)資源。
緩存驗證上一小節(jié)已經(jīng)提到,當瀏覽器請求一個資源時,如果發(fā)現(xiàn)緩存中有該資源,但是已經(jīng)過期了,那么瀏覽器就會向服務器發(fā)起 HTTP 請求,以驗證緩存的資源是否發(fā)生變化。
緩存驗證時機什么時候會進行緩存驗證?
刷新頁面。一般來說,為了確保用戶獲取到最新的數(shù)據(jù),在刷新頁面時大部分瀏覽器都不會再使用緩存中的數(shù)據(jù),而是發(fā)起一個請求去服務器驗證。
Response Header 中設(shè)置了 Cache-control: must-revalidate。當緩存的資源過期之后,必須到源服務器去驗證,只有確認該資源沒有過期,才能繼續(xù)使用緩存。
緩存驗證器服務器是怎么判斷資源改變與否的呢?服務端在返回響應內(nèi)容的同時,還會在?Response Header 中設(shè)置一些驗證標識,當緩存的資源過期之后,瀏覽器就會攜帶驗證標識向服務器發(fā)起請求,服務器通過對比這些標識,就能知道緩存的資源是否發(fā)生了改變。
Header 中的驗證標識字段主要有兩組:Etag?和?If-None-Match?、Last-Modified?和?If-Modified-Since?。其中,形如?If-xxx?這樣的請求首部字段,可以稱之為條件請求。比如只在滿足某個條件的情況下返回或上傳文件,這樣可以節(jié)省帶寬。
?
Last-Modified 就是一個驗證器。服務器在將資源返回給客戶端的同時,會將資源的最后修改時間?Last-Modified?加在 Response Header 中一起返回。瀏覽器會為資源標記上該信息,當緩存過期之后,瀏覽器會把該信息設(shè)置到?Request Header?中的 If-Modified-Since?中向服務器發(fā)起請求。
如果?If-Modified-Since 中的值和服務器上該資源最終的修改時間一致,就說明該資源沒有被修改過,服務器會直接返回 304 狀態(tài)碼,無響應實體,這樣就可以節(jié)省傳輸?shù)臄?shù)據(jù)量。如果不一致,服務器會返回 200 狀態(tài)碼,同時和第一次 HTTP 請求一樣,返回響應實體和驗證器。
Last-Modified:Fri, 04 Jan 2019 14:00:21 GMTEtag
服務器會通過某種算法,為資源計算出一個唯一標識符,在把響應返回給客戶端的時候,會在 Response Header 中加上 Etag: 唯一標識符?一起返回給客戶端。
Etag:"952d03d8561454120b550f0a5679a172c4822ce8"
客戶端會將 Etag 保存下來,后續(xù)請求時會將 Etag 作為 Request Header 中?If-None-Match?的值發(fā)給服務器。通過比對客戶端發(fā)過來的 Etag 和服務器上保存的 Etag 是否一致,就能夠知道資源是否發(fā)生了變化。如果資源沒有發(fā)生變化,返回 304,客戶端繼續(xù)使用緩存。如果資源已經(jīng)修改,則返回 200。
制定緩存策略緩存真的可以說讓我們又愛又恨。在開發(fā)時,我們經(jīng)常遇到這樣的問題:明明已經(jīng)修改了這個文件,為什么沒有生效?好吧,文件被緩存了。。。但是在上線時,我們又希望文件盡可能地被瀏覽器緩存,來提高性能。因此為自己的應用制定合適的緩存策略非常重要。
為靜態(tài)資源設(shè)置較長緩存時間。
有些資源很長時間都不會改變,比如一些三方庫,圖片,字體文件等。可以為它們設(shè)置一個很長的過期時間,例如設(shè)定「一年」。
通過給文件名的唯一標識來確保文件修改生效。
有些時候為了解決 bug,我們可能會修改一些文件,比如應用的 CSS、JS 等。如果這些文件已經(jīng)被緩存,那么除非用戶強制刷新頁面,否則用戶只有在緩存過期之后才有可能獲取新的文件。如何讓瀏覽器不使用緩存,而是重新下載新的文件呢?有一個辦法就是給文件名加上唯一標識,比如?Hash 或版本信息。當文件修改之后,這個唯一標識也會隨之改變。瀏覽器發(fā)現(xiàn)文件改變之后,就不會使用緩存了。
明確是否有資源不能被緩存。
比如一些敏感數(shù)據(jù),如果不應該被瀏覽器緩存,需要在 Response Header 中設(shè)置 Cache-Control: no-store。
調(diào)試如何知道請求的資源是否被緩存了?打開 Chrome 的開發(fā)者工具,我們可以看到 Size 這一欄下面,如果顯示文件真實的大小,則說明該文件未被緩存。如果顯示 from xxx cache,則說明該請求使用的是已被緩存的文件。如下:
調(diào)試時,如果想禁用瀏覽器緩存,可以在開發(fā)者工具上勾選 Disabel cache。
最后最后,大家可以通過下面這張圖再回顧一下我們剛剛講過的內(nèi)容。
參考HTTP 緩存
奇怪的緩存策略
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/62091.html
摘要:提交任務當創(chuàng)建了一個線程池之后我們就可以將任務提交到線程池中執(zhí)行了。提交任務到線程池中相當簡單,我們只要把原來傳入類構(gòu)造器的對象傳入線程池的方法或者方法就可以了。 我們一般不會選擇直接使用線程類Thread進行多線程編程,而是使用更方便的線程池來進行任務的調(diào)度和管理。線程池就像共享單車,我們只要在我們有需要的時候去獲取就可以了。甚至可以說線程池更棒,我們只需要把任務提交給它,它就會在合...
摘要:不努力不奮斗,可能就會在基層一輩子止步不前。不過,只一句,如果你還在做這一行,還是一名程序猿媛,想走上坡路的你,也許我這到手的十幾家一線互聯(lián)網(wǎng)公司性能優(yōu)化項目實戰(zhàn)可能會對你有所幫助。 ...
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
閱讀 2291·2023-04-26 00:01
閱讀 796·2021-10-27 14:13
閱讀 1810·2021-09-02 15:11
閱讀 3381·2019-08-29 12:52
閱讀 528·2019-08-26 12:00
閱讀 2569·2019-08-26 10:57
閱讀 3405·2019-08-26 10:32
閱讀 2848·2019-08-23 18:29