前言
緩存如果不能用以提升性能,那麼它就毫無用處。
以HTTP緩存為例,如果緩存未過期那麼就減少了網絡請求,如果緩存通過驗證那麼就減少了傳輸資源大小。而關於過期與驗證機制的講解將在下文中展開。
注:本文將提供詳細參考資料,如果你對其中細節感興趣對某個細節進行更為深入的瞭解。
瀏覽器緩存概述
瀏覽器緩存可以從多個維度進行抽象分類。在廣義上來講無論是memory cache、service worker、push cache、http cache都屬於瀏覽器緩存的概念,而大部分時候我們提到瀏覽器緩存的概念往往是指http cache。其實對於瀏覽器而言還有一種回退緩存(page cache),
以下我們來關注幾種瀏覽器可能會發生緩存的場景:
- 資源預加載: 如preloader ,preload、prefetch。preloader與preload不同是資源預加載期,例如在標記化時,可能需要的css資源就已經被預先加載到memory cache中了。而資源預加載技術,通過link實現。可以將項目中可能用到的數據先請求過來以備頁面使用。數據存放於內存緩存( memory cache)。參考:https://calendar.perfplanet.com/2013/big-bad-preloader/
- 服務端推送: 這裏是指http2的服務端推送,而非客户端輪詢。是一種服務器根據某種規則推送客户端將可能用到的資源來減少請求時間的技術。數據存放於push cache。推送緩存中的數據僅可以使用一次,之後將可能根據協議頭存在於http緩存中。參考:https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/
- service worker: Service workers 本質上充當 客户端與服務端之間的代理服務器。這個 API 創建了有效的離線體驗,它會攔截網絡請求並根據網絡是否可用採取來適當的動作、更新來自服務器的的資源。它還提供入口以推送通知和訪問後台同步 API。server woker的緩存不同於http 緩存,由server worker自身接管,存儲在server worker 參考:https://w3c.github.io/ServiceWorker/#cache-objects
- 重複的網絡資源請求: 常見的網絡資源請求,可以根據協議頭將資源存儲在硬存中,以備下一次使用(http cache),相對於內存緩存,可以進行持久化的存儲,而不會侷限於單次會話。參考:https://www.rfc-editor.org/rfc/inline-errata/rfc7234.html
- 頁面回退:想象有這樣一種場景,你點進了一個博客,順着博客的鏈接你進了另一篇文章,當你回退的時候是否會覺得上一個頁面似乎很快就會退了而非重新進行了一遍加載。這就是瀏覽器為了瀏覽器性能實現的頁面回退機制(Page Cache)。不過此種機制往往不存在於頁面內資源尋找的過程,是一種瀏覽器自身不受開發者控制的實現機制。
參考:https://calendar.perfplanet.com/2013/big-bad-preloader/
以上緩存的讀取順序為: (Memory Cache/Preload Cache) -> Service Worker -> (Disk Cache/HTTP cache) -> Push Cache
而本文主要以Http Cache的描述為主,關於Service worker以及Server Push如果感興趣可以通過參考鏈接進行過了解。
HTTP緩存概述
緩存的目標是通過重用先前的響應消息以滿足當前請求,來顯着提高性能。
讓我們來看一個小例子以便於理解:
這天瀏覽器請求一個叫做海綿寶寶.jpg的資源,服務器給了瀏覽器一張圖片。當瀏覽器再一次請求服務器海綿寶寶.jpg時,
服務器説:大哥,未來30天圖都不會變,你就不能存起來下次別來管我要了嗎?我太累了。並在響應裏寫到,這個圖30天都不變。
於是瀏覽器在這30天裏遇到這張圖的請求都會使用緩存的圖片以響應。
第31天時,瀏覽器又遇到了海綿寶寶.jpg的請求。於是他問服務器:海綿寶寶.jpg變了嗎
服務器答道:沒變
又過了一段時間,遇到這個請求時瀏覽器又去問服務器
服務器説:變了。並給了瀏覽器一張圖片。
瀏覽器這次就用新的圖片響應了請求。
記住本文的主角:瀏覽器和海綿寶寶.jpg,我們將在後文多處看到他們。(是的,服務器在本文只是配角)
前情提要:在後面我們會講述:
- 服務器如何告知圖片資源海綿寶寶.jpg的有效期
- 瀏覽器如何計算圖片是否過期(要知道這圖片是服務器轉交給瀏覽器的)
- 服務器如何根據信息得知瀏覽器的資源是不是有效的(畢竟服務器不止和一個瀏覽器對話,無法記憶只能計算)
- 如果某次,服務器沒有告知海綿寶寶.jpg這張圖片資源的過期信息,瀏覽器還會存儲資源嗎
- 瀏覽器的緩存中可能有很多張海綿寶寶.jpg資源嗎,如果有會怎麼選擇呢
- 瀏覽器會如何緩存海綿寶寶.jpg(要知道瀏覽器要處理很多請求,除了海綿寶寶.jpg,可能還有派大星.jpg,他們需要被區分)
簡單的來説當我們請求一個請求一個本地存在響應緩存的資源時,瀏覽器並不會立即發起網絡請求。而是對緩存的新鮮度(freshness)進行一個判定,如果該響應是可以使用的,那麼就會直接使用緩存資源以減少延遲和網絡開銷)。
如果緩存資源已經陳舊了,那麼就會對緩存資源進行驗證。如果驗證通過,那麼瀏覽器仍然可以複用資源,以減少網絡傳輸的資源大小。如果沒有通過,則源服務器應當在驗證請求中返回資源,而不是僅僅告訴瀏覽器該緩存不可使用。
強緩存與協商緩存:現在的許多資料中都將未過期可直接使用的緩存稱為強制緩存。過期了需要驗證的緩存稱為協商緩存。但是實際上RFC文檔中並未給出這樣的定義。也就是説這兩個概念屬於理解性的概念而非規範性的概念
為了簡單理解可以先參考下面這張圖。但是這裏隱去很多細節,隨着後文對內容的不斷擴充,我們會完善這張圖。
以上簡述,描述了網絡資源請求使用緩存的一個大致過程。以下將詳細描述過期與驗證機制。
過期機制
還記得上面海綿寶寶圖片的例子嗎,我們現在需要來解決第一個問題,即服務器如何告知圖片資源海綿寶寶.jpg的有效期。為了解決這個問題,則需要一種規範來明確定義如何説明進行資源緩存機制。這種規範必須是雙方都可以理解的。在HTTP1.1中,可以使用Cache-Control的緩存指令,以實現緩存機制。
在使用瀏覽器決定對一個內容進行緩存之前,他將會判定內容是否為可以緩存的。
- 如果緩存指令被設置為no-store,則不可以使用緩存
- 如果緩存指令被設置為private,則不可以使用作為共享緩存。即代理服務器不可以對資源進行緩存。
- 除非響應中明確包含緩存字段,否則不應該緩存Authorization首部字段的請求
- 一般來説,響應如果既沒有驗證機制也沒有過期機制,那麼通常不緩存,不過並不會禁止這樣的緩存行為
當資源緩存之後,則在重用時需要判定資源是否過期。max-age被用以設置緩存存儲的最大週期,超過這個時間緩存被認為過期(單位秒)。
對於共享緩存來説(比如各個代理),s-maxage將覆蓋max-age或者Expires頭,私有緩存會忽略它。
因此服務器如果想要告知資是30天過期時間,則需要設置:
Cache-Control: max-age=2592000
現在服務器成功的設置了過期時間,我們來到第二個問題,瀏覽器如何計算資源過期了?
其實只需要保證資源的可緩存時間大於資源的存在時間,那麼緩存就沒有過期。反之,則緩存則過期了。以下我們將討論可緩存時間(freshness LifeTime)與存在週期(Age)的具體算法。
freshness LifeTime的算法:
- 如果緩存是共享的,如存在s-maxage則使用
- 如果存在max-age響應指令,則使用其值
- 如果存在Expires首部字段,則用它的值減去Date首部字段的值
- 當響應中沒有明確指出過期時間。 將可能可能使用啓發式freshness計算
還記得,我們之前討論的問題:如果沒有約定緩存相關的內容,那麼還會緩存嗎?
答案是:不一定。一般來説如果既沒有過期説明,也沒有明確進行協商驗證。那麼不緩存。但不禁止緩存。可由瀏覽器自由發揮。一般這種自由發揮被稱之為啓發式緩存。
關於啓發式緩存的算法,通常採用Last-Modified與Date時間差的1/10來作為freshness LifeTime。關於啓發式緩存我們有兩點需要注意。
- 啓發式緩存是一個非規範性的行為,實現上會隨着瀏覽器不同存在一些差異,也可能沒有。規範上不禁止。
- 對於那些響應頭中明確指出該如何緩存的資源,明確禁止使用啓發式緩存。
Age算法:
Age首部字段被用於描述一個緩存接收到響應消息的估算時長(Age)。Age 字段的值是指消息被源服務器創建或者驗證之後以來緩存的秒數估算值。
重要的是,Age值是響應沿源服務器的路徑駐留在每個緩存中的時間的總和,並需要加上在網絡路徑中的傳輸時間
以下數據被用於計算age
- age_value: "age_value"以適合算數運算的形式表示Age首部字段。如果不可用,則為0。
- date_value: “ date_value”以適合於算術運算的形式表示Date標頭字段的值。
- now: now表示時鐘的當前值。應該使用ntp或一些類似的協議,使其時間同步UTC時間
- request_time: 發起請求使得存儲響應被觸發的時間
- response_time: 收到響應時主機時鐘的當前值
響應的age可以以兩種完全獨立的方式計算
- apparent_age:如果本地時鐘與原始服務器的時鐘是協調同步的,response_time減去date_value。 否則,結果將被替換為零
- corrected_age_value:如果沿響應路徑的所有緩存實現HTTP / 1.1,緩存必須相對於啓動請求的時間來解釋此值,而非收到響應的時間
這裏簡單説下,為什麼http1.1需要使用request時間進行校正。因為http1.1的存儲最大週期時間是相對於請求的時間的。
apparent_age = max(0, response_time - date_value);
response_delay = response_time - request_time;
corrected_age_value = age_value + response_delay
合併為
corrected_initial_age = max(apparent_age, corrected_age_value)
如果緩存對Age首部字段的值置信(例如,沒有HTTP / 1.0 hops存在於Via首部字段中),則在這種情況下,corrected_age_value可以用作corrected_initial_age
存儲響應時間可以通添加存儲響應最後一次被源服務器驗證(以秒為單位)與corrected_initial_age的和值來計算
resident_time = now - response_time;
current_age = corrected_initial_age + resident_time
看到這,可能會令人頭禿。簡單的總結一下:
Age 消息頭裏包含對象在緩存代理中存貯的時長,以秒為單位。這裏描述了Age首部字段的算法。
而緩存存在週期的算法則是:上一次收到服務器答覆距離現在的時間的差值和在代理服務器中存貯的時間之和。即緩存在瀏覽器存在的時長+緩存在代理服務器路徑上存在的時長。
關於過期機制的三個首部字段分別為:
Cache-Cotrol:Cache-Control是緩存控制的重要字段,如果要系統的瞭解它的各項指令,那麼最好的方式是讀RFC文檔,或者MDN文檔。本文不會詳解cache-control的每個指令,而會去一些容易混淆的點擊進行概述。
- 緩存指令是從多個維度描述緩存的。例如
Cache-Control:public, max-age=31536000包含了資源的可緩存性以及過期特性。 - no-cache不是禁用緩存,no-store才是。如果顯式的使用了no-store,則瀏覽器不能使用啓發式緩存。
- 如果希望緩存每次都使用驗證機制,則可以使用no-cache,或者把max-age設置為0(如果是Expires,則可以把它設置為一個顯然過期了的時間)。
Expires:該字段提供了一個日期,在該日期之後的資源被認為是過期的。關於Expires需要注意的是:
- 如果存在max-age,則該值被忽略。
- 如果共享緩存存在s-maxage,則該值被忽略
- 採用極大值時,將可能導致問題(例如,由於對時間值使用32位整數而導致時鐘溢出)
- 如果存在多個Expires字段,則被視為無效
Pragma:Pragma 是一個在 HTTP/1.0 中規定的通用首部,這個首部的效果依賴於不同的實現,所以在“請求-響應”鏈中可能會有不同的效果。它用來向後兼容只支持 HTTP/1.0 協議的緩存服務器,那時候 HTTP/1.1 協議中的 Cache-Control 還沒有出來。
- 當請求中沒有 Cache-Control 頭字段時,緩存必須將無緩存請求 pragma-directive 視為具有與“ Cache-Control: no-cache”存在時相同的效果
- 在發送無緩存請求時,客户機應該同時包含pragma和-control指令
- no-cache這個指令不是規範性的,因此本方案不能可靠替代Cache-Control
根據以上的過期機制,如果緩存被判定為未過期的,則可以在不與源服務器連接的情況下直接使用緩存響應消息。否則則應當使用驗證機制。以下將展開講述驗證機制。
驗證機制
上節中講到了過期機制的判定。當一個資源過期,或者初始時就被設置為強制驗證等原因導致緩存無法提供響應時,它可以使用條件請求機制在轉發請求到源服務器以選擇一個有效響應。這個過程被稱為驗證。關於條件請求機制如果你感興趣可以參閲條件請求和分佈式創作及版本控制
還記得上文海綿寶寶的例子嗎?下來我們將討論第三個問題服務器如何驗證緩存資源。值得一提的是在這個部分服務器化身主角了。
如果需要服務器能夠快速驗證本地資源相對於緩存資源的變更,我們需要有一個標示幫助服務器進行快速比對。如果每次有效更新這個值都會變更,反之則不會變更,那麼服務器就能快速判斷本地資源相對於緩存資源是否有變更了。我們將可以幫助我們驗證的方式為驗證器
在正式介紹驗證器之前我們不妨想想什麼樣的標示可以用於判斷資源變更比對。
如果文件內容變更了,因此內容散列也會變更,反正內容散列則不會變更。因此我們可以使用內容散列作為驗證器,記錄內容散列的字段是ETag。
而另一種比較簡單粗暴的方式則是判定文件的最後一次修改時間。如果文件的最後一次修改時間變更了,我們認為文件變更了。反之,則認為沒有變更。記錄文件最後一次變更時間的字段是Last-Modified。
強驗證器與弱驗證器: 我們將驗證器分為兩種:強驗證器與弱驗證器。弱驗證器是易於生成,但對驗證來熟存在許多限制甚至缺陷。強驗證器是比較的理想選擇,但可能非常困難(並且有時是不可能的)以高效地生成。Last-Modified是顯式弱驗證器除非能證明是強選擇器。而ETag默認為強驗證器,但我們可以顯示的將其指為弱驗證器。
當然了相比於內容散列,使用最後一次修改時間會有一些缺陷,所以通常作為候補方案來使用。下面我們將詳細介紹這兩種驗證器:
Last-Modified:其中包含源頭服務器認定的資源做出修改的日期及時間。 它通常被用作一個驗證器來判斷接收到的或者存儲的資源是否彼此一致。由於精確度比 ETag 要低,所以這是一個備用機制。
這裏我們給出一個示例:
Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
對應條件請求機制:請求可以在請求首部If-Modified-Since中攜帶上需要驗證的響應用於響應驗證。服務器只在所請求的資源在給定的日期時間之後對內容進行過修改的情況下才會將資源返回,狀態碼為200 。如果請求的資源從那時起未經修改,那麼返回一個不帶有消息主體的304響應。
下面我們做一個總結:
- Last-Modified/If-Modified-Since用於資源驗證。如果資源未變更,響應中不會發返回消息主體。
- 其驗證優先級將低於下面要講到的ETag。因此驗證時,如果存在If-None-Match,則If-Modified-Since會被忽略
- Last-Modified值也可以被If-Unmodified-Since或If-Range字段攜帶以表示條件選擇。在這種情況下,只有當資源在指定的時間之後沒有進行過修改的情況下,服務器才會返回請求的資源。如果所請求的資源在指定的時間之後發生了修改,那麼會返回412錯誤。需要注意這是條件請求機制而非驗證機制。此處提及,是避免與If-Modified-Since。因為看到有些文章中覺得這兩個字段都用於緩存校驗,這種説法是不正確的。
ETag:ETag響應頭是資源的特定版本的標識符。其用法如下:
- ETag實體標籤是不透明的驗證器,用以區分相同的多個表示資源,而不管資源狀態是否隨時間變化。
-
可以通過添加W/將Etag指為弱驗證器。例如以下表示中,不帶w/的默認使用強驗證器,而w/則顯示標明使用弱驗證器
ETag: W/"<etag_value>" ETag: "<etag_value>" - ETag/If-None-Match被用於進行緩存校驗。ETag 屬性之間的比較採用的是弱比較算法,即兩個文件除了每個比特都相同外,內容一致也可以認為是相同的。例如,如果兩個頁面僅僅在頁腳的生成時間有所不同,就可以認為二者是相同的。
- If-Match:表示這是一個條件請求。如果資源匹配才返回,不匹配返回416.需要注意這是條件請求機制而非驗證機制。這裏提出只是區分上文的If-None-Match。避免混淆。這種機制一般用於解決空中碰撞問題而非緩存驗證。
空中碰撞: 想象有這樣一種場景。你正在編輯一個文檔,文檔現在的版本是v1.0。因此你目前的變更時基於v1.0的。但等你提交的時候,由於小明比你先提交,所以服務器的版本已經變成小明提交的v1.1。如果你成功提交,則小明編輯的內容就會消失。這種情況稱為空中碰撞。為了檢測到這種情況,瀏覽器會提交If-Match或者If-Unmodified-Since進行條件請求,如果條件符合,則可以成功提交,否則返回412前提條件失敗。如果對此感興趣,可參閲:https://www.w3.org/1999/04/Editing/
整體梳理
為了方便理解,放了一張圖來簡述上文介紹的緩存過程:
還記得海綿寶寶.jpg那裏我們提出的問題嗎?通過上述章節的介紹我們可以來試試回答了。當然你也可以不往下翻而是回去看看那些問題,並幫助瀏覽器解決問題。
- 服務器如何告知圖片資源海綿寶寶.jpg的有效期?
- 瀏覽器如何計算圖片是否過期(要知道這圖片是服務器轉交給瀏覽器的)
- 服務器如何根據信息得知瀏覽器的資源是不是有效的(畢竟服務器不止和一個瀏覽器對話,無法記憶只能計算)
- 如果某次,服務器沒有告知海綿寶寶.jpg這張圖片資源的過期信息,瀏覽器還會存儲資源嗎
- 瀏覽器的緩存中可能有很多張海綿寶寶.jpg資源嗎,如果有會怎麼選擇呢
- 瀏覽器會如何緩存海綿寶寶.jpg(要知道瀏覽器要處理很多請求,除了海綿寶寶.jpg,可能還有派大星.jpg,他們需要被區分)
下面我們來揭曉答案:
1、通過過期機制。就緩存時長而言,通常是max-age指令與Expires首部字段。
詳細內容可以參閲過期機制章節。
2、通過比對freshness lifetiime與age來判定。
3、通過驗證機制。詳細內容可以參閲驗證機制章節。
4、這是一個不確定的答案,或許我們要看瀏覽器本身的意願。通常不會,不過瀏覽器自身可以採用啓發式過期週期計算。
5、這道題在上文中並沒有提到,所以我們似乎還不能做出解答
6、同樣,這也是我們目前瞭解到的內容無法解決的問題。
那麼我們需要繼續深入一些細節,以幫助瀏覽器解決所有的問題。
- 緩存如何在瀏覽器內進行存儲
如果要標示緩存資源那麼最直接的方式就是以url以及請求方法作為主鍵進行存儲。實際上RFC的規範也確實如此。但是鑑於,實際上請求方法往往被限制為get,因此可以只使用url作為主鍵。關於瀏覽器具體實現可以參閲:https://www.chromium.org/developers/design-documents/network-stack/disk-cache - 是否可能同一資源對應多條緩存
如果請求目標受內容協商影響,則其緩存記錄可能包含多個響應存儲內容,每個存儲響應由原始請求選擇標題字段的值作為輔助密鑰來進行區分。用Vary首部字段來實現。當緩存收到了一個可以被帶有Vary首部字段的存儲,除非可以滿足Vary字段中所有選擇的首部字段,否則不應當使用該響應。
而如果有多條緩存都可以滿足條件,緩存將需要選擇其中的一個進行使用。如果存在一個選擇首部字段擁有一種已知機制可以進行擇優(例如,Accept中的qvalues值,以及相似的請求首部字段),那麼該機制就可能用作選擇更優的響應。如果沒有這樣的機制,將會通過Date首部字段根據最近日期選擇一個最近期的響應。
到了這裏,我們的旅程就結束了。期間,我們幫助瀏覽器完成了他關於海綿寶寶.jpg的緩存使命。相信這將是一次難忘的旅程。:)
在後文中將附上一些容易出現的誤解和在這個過程中參閲的資料。如果對於這趟旅程的細節你還想了解更多,不妨繼續閲讀下去!
易混淆內容
在閲讀RFC文檔及瀏覽器相關文檔後發現目前許多關於緩存的文章都不夠全面,甚至有誤,這裏先整理幾個常見的誤區。
強制緩存與協商緩存:
從便於理解的角度來講沒有問題,但這不是規範中的概念。實際上IETF中關於HTTP的Cache規範主要從過期機制與驗證機制來描述緩存。可參閲RFC7234全文
強緩存與弱緩存概念:
緩存概念並不區分強弱。是緩存驗證機制中的驗證器分為強驗證器與弱驗證器。
可參閲RFC7232第2.1節
有了ETag就不需要Last-Modified:
事實上,這兩種都應該存在。因為你不能保證路徑上都是HTTP1.1協議。對於不能理解ETag的協議來説,緩存將失效。而假如都有,那對於可以理解ETag的則會忽略last-Modified,因此有益無害。Cache-Control與Expires同理。可參閲RFC7232第2.4節
memory cache和disk cache是http緩存的兩個位置:
仔細看network就會發現size那一欄有時會出現disk cache有時候會出現memory cache。所以http緩存會根據一定規則決定存進內存還是硬存?
並不是這樣,memory cache和http cache是並列的緩存類型,沒有包含關係。http cache作為持久化存儲一定會進入disk的,所以disk cache和http cache是一種存儲方式。
要證明memory cache不是http cache的一部分是很簡單的。因為開發者可以在開發中工具的network裏禁用緩存。首先我們直接加載一次請求
可以看到資源有的從memory cache加載,有的從disk cache加載。現在打開禁用緩存。
當顯示的禁用緩存後,從disk加載的已經直接請求了。memory cache的依然從memory cache去讀取。可見資源的可緩存性不影響memory cache的行為。
在前面的講述中我們已經知道memory cache優先級大於disk cache。設若一個資源是不可長期緩存的,例如設置了no-store,但是並不會影響其內存是否緩存的行為。反之如果memory cache的資源如果被設定為可存儲他最終一定也是會進入硬存持久化存儲的。
我們考慮一個內容有什麼用很難,我們反向思考一下沒有memory cache會發生什麼。我們加載了一張圖用做頭像框。整個頁面有10個頭像要加載。如果這張圖被服務器標不可以緩存,瀏覽器真的不緩存他就要把同一張圖加載10遍。這合理嗎?這不合理,所以memory cache不屬於http緩存的一種形式,不受協議影響,是一種短效快捷存儲。
mozilla提供了關於內存緩存關閉的選項。其中對默認緩存內容進行了描述。其默認是開啓的。可參見mozilla的memory cache配置。不同瀏覽器實現可能存在差異。
附錄
關於緩存需要了解的首部字段
| 字段名稱 | 參考文檔 | 字段類型 | 字段描述 |
|---|---|---|---|
| Age | https://developer.mozilla.org... | 響應首部 | Age 消息頭裏包含對象在緩存代理中存貯的時長,以秒為單位。. |
| Pragma | https://developer.mozilla.org... | 通用首部 | 它用來向後兼容只支持 HTTP/1.0 協議的緩存服務器 |
| Date | https://developer.mozilla.org... | 通用首部 | 包含了報文創建的日期和時間。 |
| Vary | https://developer.mozilla.org... | 響應首部 | 它被服務器用來表明在 內容協商算法中選擇一個資源代表的時候應該使用哪些頭部信息 |
| Last-Modified | https://developer.mozilla.org... | 響應首部 | 包含源頭服務器認定的資源做出修改的日期及時間。 |
| If-Modified-Since | https://developer.mozilla.org... | 請求首部 | 服務器只在所請求的資源在給定的日期時間之後對內容進行過修改的情況下才會將資源返回。 |
| If-Unmodified-Since | https://developer.mozilla.org... | 請求首部 | 如果所請求的資源在指定的時間之後發生了修改,那麼會返回 412 (Precondition Failed) 錯誤。 |
| ETag | https://developer.mozilla.org... | 請求首部 | ETagHTTP響應頭是資源的特定版本的標識符。 |
| If-Match | https://developer.mozilla.org... | 請求首部 | 服務器僅在請求的資源滿足此首部列出的 ETag值時才會返回資源 |
| If-None-Match | https://developer.mozilla.org... | 請求首部 | 當且僅當服務器上沒有任何資源的 ETag 屬性值與這個首部中列出的相匹配的時候,服務器端會才返回所請求的資源 |
| If-Range | https://developer.mozilla.org... | 請求首部 | If-Range字段用來使得Range頭字段在一定條件下起作用:當字段值中的條件得到滿足時,Range 頭字段才會起作用,同時服務器回覆206 部分內容狀態碼 |
| Expires | https://developer.mozilla.org... | 實體首部 | Expires 響應頭包含日期/時間, 即在此時候之後,響應過期。 |
| cache-control | https://developer.mozilla.org... | 通用首部 | 用於在http請求和響應中,通過指定指令來實現緩存機制 |
參考文檔
- preload:https://developer.mozilla.org...
- server push:https://blog.csdn.net/wetest_...
- https://jakearchibald.com/201...
- push cache:https://www.cnblogs.com/xgqfr...
- webkit頁面緩存:https://webkit.org/blog/427/w...
- chromium硬盤存儲:https://www.chromium.org/deve...
- http緩存:https://www.chromium.org/deve...
- 內存緩存:http://kb.mozillazine.org/Bro...
- http://kb.mozillazine.org/Bro...
- chromium:https://www.chromium.org/deve...
- web worker:https://www.chromium.org/blin...
- http://www.whatwg.org/specs/w...
- https://docs.google.com/docum...
- blink worker:https://docs.google.com/docum...
- 進程間通信:https://www.chromium.org/deve...
- 多進程資源加載:https://www.chromium.org/deve...
- chromium如何顯示網頁面:https://www.chromium.org/deve...
- 資源請求:https://chromium.googlesource...
- gpu程序緩存:https://docs.google.com/docum...
- 渲染:https://docs.google.com/docum...
- 重繪原理:https://docs.google.com/docum...
- https://ci.chromium.org/p/chr...
- 視覺格式化模型:https://www.w3.org/TR/CSS21/v...
- 瀏覽器:http://taligarsiel.com/Projec...
- html:https://whatwg-cn.github.io/h...
- webcore渲染 https://webkit.org/blog/114/
- http rfc https://www.ietf.org/rfc/rfc2...
- ietf rfc查詢 https://www.rfc-editor.org/se...
- url 解析https://webkit.org/blog/7086/...
- server worker: https://webkit.org/blog/8090/...
- webworker緩存:https://w3c.github.io/Service...
- server push規範:https://www.rfc-editor.org/rf...
- https://www.rfc-editor.org/rf...
- url加載:https://developer.chrome.com/...
- chrome 緩存:https://developer.chrome.com/...
- loader:https://calendar.perfplanet.c...
- http緩存:https://www.w3.org/Protocols/...
- 緩存協議:https://www.rfc-editor.org/rf... https://www.rfc-editor.org/rf...
- http1.1 https://www.w3.org/Protocols/... (已被7230~7237取代)
- http1.0:https://www.ietf.org/rfc/rfc1...
- http:https://www.rfc-editor.org/se...
- 文檔變更檢測(空中碰撞):https://www.w3.org/1999/04/Ed...