前端優(yōu)化之三:詳解http緩存

轉(zhuǎn)載自https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching

通過網(wǎng)絡獲取內(nèi)容既速度緩慢又開銷巨大捻爷。較大的響應需要在客戶端與服務器之間進行多次往返通信份企,這會延遲瀏覽器獲得和處理內(nèi)容的時間巡莹,還會增加訪問者的流量費用降宅。因此,緩存并重復利用之前獲取的資源的能力成為性能優(yōu)化的一個關鍵方面腰根。

好在每個瀏覽器都自帶了 HTTP 緩存實現(xiàn)功能额嘿。您只需要確保每個服務器響應都提供正確的 HTTP 標頭指令,以指示瀏覽器何時可以緩存響應以及可以緩存多久东帅。

注:如果您在應用中使用 Webview 來獲取和顯示網(wǎng)頁內(nèi)容球拦,可能需要提供額外的配置標志帐我,以確保 HTTP 緩存得到啟用愧膀、其大小根據(jù)用例進行了合理設置并且緩存將持久保存檩淋。務必查看平臺文檔并確認您的設置!


image.png

當服務器返回響應時碳柱,還會發(fā)出一組 HTTP 標頭熬芜,用于描述響應的內(nèi)容類型涎拉、長度、緩存指令鼓拧、驗證令牌等季俩。例如,在上圖的交互中店归,服務器返回一個 1024 字節(jié)的響應酪我,指示客戶端將其緩存最多 120 秒,并提供一個驗證令牌(“x234dff”)秩伞,可在響應過期后用來檢查資源是否被修改欺矫。

通過 ETag 驗證緩存的響應

TL;DR

  • 服務器使用 ETag HTTP 標頭傳遞驗證令牌汇陆。
  • 驗證令牌可實現(xiàn)高效的資源更新檢查:資源未發(fā)生變化時不會傳送任何數(shù)據(jù)。

假定在首次獲取資源 120 秒后阅羹,瀏覽器又對該資源發(fā)起了新的請求。首先执庐,瀏覽器會檢查本地緩存并找到之前的響應导梆。遺憾的是,該響應現(xiàn)已過期递鹉,瀏覽器無法使用藏斩。此時狰域,瀏覽器可以直接發(fā)出新的請求并獲取新的完整響應。不過屈溉,這樣做效率較低抬探,因為如果資源未發(fā)生變化驶睦,那么下載與緩存中已有的完全相同的信息就毫無道理可言匿醒!

這正是驗證令牌(在 ETag 標頭中指定)旨在解決的問題。服務器生成并返回的隨機令牌通常是文件內(nèi)容的哈希值或某個其他指紋溉痢『⒈客戶端不需要了解指紋是如何生成的竹挡,只需在下一次請求時將其發(fā)送至服務器揪罕。如果指紋仍然相同宝泵,則表示資源未發(fā)生變化儿奶,您就可以跳過下載鳄抒。

image.png

在上例中许溅,客戶端自動在“If-None-Match” HTTP 請求標頭內(nèi)提供 ETag 令牌。服務器根據(jù)當前資源核對令牌娱仔。如果它未發(fā)生變化牲迫,服務器將返回“304 Not Modified”響應借卧,告知瀏覽器緩存中的響應未發(fā)生變化铐刘,可以再延用 120 秒镰吵。請注意,您不必再次下載響應盼产,這節(jié)約了時間和帶寬勺馆。

作為網(wǎng)絡開發(fā)者,您如何利用高效的重新驗證草穆?瀏覽器會替我們完成所有工作:它會自動檢測之前是否指定了驗證令牌悲柱,它會將驗證令牌追加到發(fā)出的請求上豌鸡,并且它會根據(jù)從服務器接收的響應在必要時更新緩存時間戳轴总。我們唯一要做的就是確保服務器提供必要的 ETag 令牌怀樟。檢查您的服務器文檔中有無必要的配置標志往堡。

注:提示:HTML5 Boilerplate 項目包含所有最流行服務器的配置文件樣例共耍,其中為每個配置標志和設置都提供了詳細的注解痹兜。在列表中找到您喜愛的服務器字旭,查找合適的設置遗淳,然后復制/確認您的服務器配置了推薦的設置。

Cache-Control

TL;DR

  • 每個資源都可通過 Cache-Control HTTP 標頭定義其緩存策略
  • Cache-Control 指令控制誰在什么條件下可以緩存響應以及可以緩存多久拆讯。

從性能優(yōu)化的角度來說养叛,最佳請求是無需與服務器通信的請求:您可以通過響應的本地副本消除所有網(wǎng)絡延遲,以及避免數(shù)據(jù)傳送的流量費用弃甥。為實現(xiàn)此目的爽室,HTTP 規(guī)范允許服務器返回 Cache-Control 指令肮之,這些指令控制瀏覽器和其他中間緩存如何緩存各個響應以及緩存多久。

注:Cache-Control 標頭是在 HTTP/1.1 規(guī)范中定義的,取代了之前用來定義響應緩存策略的標頭(例如 Expires)丑瞧。所有現(xiàn)代瀏覽器都支持 Cache-Control,因此稽屏,使用它就夠了狐榔。

image.png

“no-cache”和“no-store”

“no-cache”表示必須先與服務器確認返回的響應是否發(fā)生了變化,然后才能使用該響應來滿足后續(xù)對同一網(wǎng)址的請求庵楷。因此楣颠,如果存在合適的驗證令牌 (ETag)蜓斧,no-cache 會發(fā)起往返通信來驗證緩存的響應挎春,但如果資源未發(fā)生變化直奋,則可避免下載脚线。

相比之下邮绿,“no-store”則要簡單得多船逮。它直接禁止瀏覽器以及所有中間緩存存儲任何版本的返回響應挖胃,例如酱鸭,包含個人隱私數(shù)據(jù)或銀行業(yè)務數(shù)據(jù)的響應凹髓。每次用戶請求該資產(chǎn)時饵沧,都會向服務器發(fā)送請求捷泞,并下載完整的響應锁右。

“public”與“private”

如果響應被標記為“public”咏瑟,則即使它有關聯(lián)的 HTTP 身份驗證码泞,甚至響應狀態(tài)代碼通常無法緩存,也可以緩存響應宋舷。大多數(shù)情況下祝蝠,“public”不是必需的绎狭,因為明確的緩存信息(例如“max-age”)已表示響應是可以緩存的儡嘶。

相比之下承疲,瀏覽器可以緩存“private”響應。不過啼辣,這些響應通常只為單個用戶緩存,因此不允許任何中間緩存對其進行緩存富弦。例如腕柜,用戶的瀏覽器可以緩存包含用戶私人信息的 HTML 網(wǎng)頁,但 CDN 卻不能緩存唉铜。

“max-age”

指令指定從請求的時間開始潭流,允許獲取的響應被重用的最長時間(單位:秒)。例如熬甫,“max-age=60”表示可在接下來的 60 秒緩存和重用響應椿肩。

定義最佳 Cache-Control 策略

image.png

按照以上決策樹為您的應用使用的特定資源或一組資源確定最佳緩存策略。在理想的情況下盖矫,您的目標應該是在客戶端上緩存盡可能多的響應辈双,緩存盡可能長的時間,并且為每個響應提供驗證令牌证芭,以實現(xiàn)高效的重新驗證。

屏幕快照 2018-01-18 14.36.05.png

根據(jù) HTTP Archive,在排名最高的 300,000 個網(wǎng)站(按照 Alexa 排名)中泛源,所有下載的響應中幾乎有半數(shù)可由瀏覽器緩存达箍,這可以大量減少重復的網(wǎng)頁瀏覽和訪問。當然,這并不意味著您的特定應用有 50% 的資源可以緩存邻辉。一些網(wǎng)站的資源 90% 以上都可以緩存,而其他網(wǎng)站可能有許多私密或時效要求高的數(shù)據(jù)根本無法緩存吱瘩。

請審核您的網(wǎng)頁蜜徽,確定哪些資源可以緩存,并確保它們返回正確的 Cache-Control 和 ETag 標頭怜械。

廢棄和更新緩存的響應

TL;DR

  • 在資源“過期”之前峡扩,將一直使用本地緩存的響應教届。
  • 您可以通過在網(wǎng)址中嵌入文件內(nèi)容指紋,強制客戶端更新到新版本的響應。
  • 為獲得最佳性能,每個應用都需要定義自己的緩存層次結構家夺。

瀏覽器發(fā)出的所有 HTTP 請求會首先路由到瀏覽器緩存惨好,以確認是否緩存了可用于滿足請求的有效響應昧狮。如果有匹配的響應合住,則從緩存中讀取響應笨使,這樣就避免了網(wǎng)絡延遲和傳送產(chǎn)生的流量費用。

不過,如果您想更新或廢棄緩存的響應,該怎么辦派继?例如认轨,假定您已告訴訪問者將某個 CSS 樣式表緩存長達 24 小時 (max-age=86400)昨稼,但設計人員剛剛提交了一個您希望所有用戶都能使用的更新霍掺。您該如何通知擁有現(xiàn)在“已過時”的 CSS 緩存副本的所有訪問者更新其緩存牙丽?在不更改資源網(wǎng)址的情況下,您做不到铜涉。

瀏覽器緩存響應后,緩存的版本將一直使用到過期(由 max-age 或 expires 決定)盖彭,或一直使用到由于某種其他原因從緩存中刪除纹烹,例如用戶清除了瀏覽器緩存。因此召边,構建網(wǎng)頁時铺呵,不同的用戶可能最終使用的是文件的不同版本;剛獲取了資源的用戶將使用新版本的響應掌实,而緩存了早期(但仍有效)副本的用戶將使用舊版本的響應陪蜻。

所以,如何才能魚和熊掌兼得:客戶端緩存和快速更新贱鼻?您可以在資源內(nèi)容發(fā)生變化時更改它的網(wǎng)址,強制用戶下載新響應滋将。通常情況下邻悬,可以通過在文件名中嵌入文件的指紋或版本號來實現(xiàn) - 例如 style.x234dff.css。

image.png

因為能夠定義每個資源的緩存策略随闽,所以您可以定義“緩存層次結構”父丰,這樣不但可以控制每個響應的緩存時間,還可以控制訪問者看到新版本的速度掘宪。為了進行說明蛾扇,我們一起分析一下上面的示例:

  • HTML 被標記為“no-cache”,這意味著瀏覽器在每次請求時都始終會重新驗證文檔魏滚,并在內(nèi)容變化時獲取最新版本镀首。此外,在 HTML 標記內(nèi)鼠次,您在 CSS 和 JavaScript 資產(chǎn)的網(wǎng)址中嵌入指紋:如果這些文件的內(nèi)容發(fā)生變化更哄,網(wǎng)頁的 HTML 也會隨之改變,并會下載 HTML 響應的新副本腥寇。
  • 允許瀏覽器和中間緩存(例如 CDN)緩存 CSS成翩,并將 CSS 設置為 1 年后到期。請注意赦役,您可以放心地使用 1 年的“遠期過期”麻敌,因為您在文件名中嵌入了文件的指紋:CSS 更新時網(wǎng)址也會隨之變化。
  • JavaScript 同樣設置為 1 年后到期掂摔,但標記為 private术羔,這或許是因為它包含的某些用戶私人數(shù)據(jù)是 CDN 不應緩存的职辅。
  • 圖像緩存時不包含版本或唯一指紋,并設置為 1 天后到期聂示。

您可以組合使用 ETag域携、Cache-Control 和唯一網(wǎng)址來實現(xiàn)一舉多得:較長的過期時間、控制可以緩存響應的位置以及隨需更新鱼喉。

緩存檢查清單

不存在什么最佳緩存策略秀鞭。您需要根據(jù)通信模式、提供的數(shù)據(jù)類型以及應用特定的數(shù)據(jù)更新要求扛禽,為每個資源定義和配置合適的設置锋边,以及整體的“緩存層次結構”。

在制定緩存策略時编曼,您需要牢記下面這些技巧和方法:

  • 使用一致的網(wǎng)址:如果您在不同的網(wǎng)址上提供相同的內(nèi)容豆巨,將會多次獲取和存儲這些內(nèi)容。提示:請注意掐场,網(wǎng)址區(qū)分大小寫往扔。
  • 確保服務器提供驗證令牌 (ETag):有了驗證令牌,當服務器上的資源未發(fā)生變化時熊户,就不需要傳送相同的字節(jié)萍膛。
  • 確定中間緩存可以緩存哪些資源:對所有用戶的響應完全相同的資源非常適合由 CDN 以及其他中間緩存進行緩存。
  • 為每個資源確定最佳緩存周期:不同的資源可能有不同的更新要求嚷堡。為每個資源審核并確定合適的 max-age蝗罗。
  • 確定最適合您的網(wǎng)站的緩存層次結構:您可以通過為 HTML 文檔組合使用包含內(nèi)容指紋的資源網(wǎng)址和短時間或 no-cache 周期,來控制客戶端獲取更新的速度蝌戒。
  • 最大限度減少攪動:某些資源的更新比其他資源頻繁串塑。如果資源的特定部分(例如 JavaScript 函數(shù)或 CSS 樣式集)會經(jīng)常更新,可以考慮將其代碼作為單獨的文件提供北苟。這樣一來桩匪,每次獲取更新時,其余內(nèi)容(例如變化不是很頻繁的內(nèi)容庫代碼)可以從緩存獲取粹淋,從而最大限度減少下載的內(nèi)容大小吸祟。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市桃移,隨后出現(xiàn)的幾起案子屋匕,更是在濱河造成了極大的恐慌,老刑警劉巖借杰,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件过吻,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機纤虽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門乳绕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逼纸,你說我怎么就攤上這事洋措。” “怎么了杰刽?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵菠发,是天一觀的道長。 經(jīng)常有香客問我贺嫂,道長滓鸠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任第喳,我火速辦了婚禮糜俗,結果婚禮上,老公的妹妹穿的比我還像新娘曲饱。我一直安慰自己悠抹,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布渔工。 她就那樣靜靜地躺著锌钮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪引矩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天侵浸,我揣著相機與錄音旺韭,去河邊找鬼。 笑死掏觉,一個胖子當著我的面吹牛区端,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播澳腹,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼织盼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了酱塔?” 一聲冷哼從身側(cè)響起沥邻,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羊娃,沒想到半個月后唐全,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡蕊玷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年邮利,在試婚紗的時候發(fā)現(xiàn)自己被綠了弥雹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡延届,死狀恐怖剪勿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情方庭,我是刑警寧澤厕吉,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站二鳄,受9級特大地震影響赴涵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜订讼,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一髓窜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧欺殿,春花似錦寄纵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至棍潘,卻和暖如春恃鞋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亦歉。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工恤浪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肴楷。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓水由,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赛蔫。 傳聞我的和親對象是個殘疾皇子砂客,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355