整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          瀏覽器強緩存和弱緩存的效果演示

          文對強緩存和弱緩存進行講解:

          為了展示強緩存和弱緩存

          第一步:Ctrl + shift + delete將緩存給清除

          將瀏覽器的數據給清空一下

          這里的數據大小是83.4kB

          在響應頭里面,會存在著ETag和Last-Modified資料

          第一請求和第二請求,這里多了一個If-Modified,在弱緩存當中,從緩存中獲取數據,檢驗匹配是經過多次匹配,出現304指令,

          200或者304指令意味著沒有發生變化

          如果是強緩存這里根本不會產生數據,強緩存的特性是存儲在用戶的本地

          瀏覽器緩存相關指令

          expires指令

          expires:該指令用來控制頁面緩存的作用。可以通過該指令控制HTTP應 答中的“Expires"和”Cache-Control"


          expires 有兩種語法,一種是time,time是時間值,它默認是以秒來計數的

          no-cache,無論緩存有沒有過期,都需要發送請求,檢驗緩存有沒有過期

          max-age與expires的意思差不多,只不過有的沒有這個配置,

          epoch會指定1970的時間,max是2037年的時間

          具體配置流程:

          vim ngnix.conf

          為了方便對比,先將請求頭信息進行復制

          之后在conf配置文件下配置

          location ~ .*\.(html|js|css|png) $ {

          }

          以html和js和css等結尾的資源,都走這個

          寫成expiress 1000;的意思是緩存1000s

          檢驗語法,重新加載

          重新對jQuery.js中進行查看

          現在相應頭多了一塊時間max-age=1000秒和Expires:Mon.27(Expires的意思是服務器的時間)

          如果將配置expiress修改為-1000,改為了負數,在請求頭中出現了no-cache

          如果將該值指定為max

          它會出現一些時間,默認是以秒來分割的

          這個max的值是10年的意思,意思是最大的緩存時間可以已達到10年

          add_header指令

          add_header指令是用來添加指定的響應頭和響應值。

          語法 add_header name value [always];

          位置存儲在http、server、location..

          如果想要到web服務器直接獲取,不緩存,用no-store

          不緩存的寫法配置,在配置文件中添加add_header Cache-Control no-store

          現在就實現了弱緩存,第一次訪問了304kb數據,第二次就是83.5kb,實現了弱緩存了

          ttp緩存:

          Web 緩存是可以自動保存常見文檔副本的 HTTP 設備。當 Web 請求抵達緩存時, 如果本地有“已緩存的”副本,就可以從本地存儲設備而不是原始服務器中提取這 個文檔。

          使用緩存主要有如下幾個優點:

          • 緩存減少了冗余的數據傳輸,節省了你的網絡費用。
          • 緩存緩解了網絡瓶頸問題。不需要更多的帶寬就能夠更快的加載頁面。
          • 緩存降低了對原始服務器的要求。服務器可以更快地響應,避免過載的出現。
          • 緩存降低了距離時延,因為從較遠的地方加載頁面會更慢一些。

          緩存的處理步驟:

          一個緩存從接收到請求到做出響應,大概可以分為如下7個步驟:

          1. 接收——緩存從網絡中讀取抵達的請求報文。
          2. 解析——緩存對報文進行解析,提取出URL和各種首部。
          3. 查詢——緩存查看是否有本地副本可用,如果沒有,就獲取一份副本(并將其保存在本地)。
          4. 新鮮度檢測——緩存查看已緩存副本是否足夠新鮮,如果不是,就詢問服務器是否有任何更新。
          5. 創建響應——緩存會用新的首部和已緩存的主體來構建一條響應報文。
          6. 發送——緩存通過網絡將響應發回給客戶端。
          7. 日志——緩存可選地創建一個日志文件條目來描述這個事務。

          Http緩存流程圖:

          狀態碼區別:

          • 200 請求成功,服務器返回全新的數據
          • 200 from memory cache / from disk cache 本地強緩存還在有效期,直接使用本地緩存
          • 304 請求成功,走了協商緩存,服務器判定(Etag和Last-modified)沒有過期,告知瀏覽器使用緩存

          業務中的使用場景:

          項目中,我們主要使用緩存來存儲html、css、js、img等靜態資源,一般不會去存儲動態資源,因為對動態資源的緩存會對數據實時性造成影響

          1、強制緩存

          強緩存是當我們訪問URL的時候,不會向服務器發送請求,直接從緩存中讀取資源,但是會返回200的狀態碼。

          我們第一次進入頁面,請求服務器,然后服務器進行應答,瀏覽器會根據response Header來判斷是否對資源進行緩存,如果響應頭中expires、pragma或者cache-control字段,代表這是強緩存,瀏覽器就會把資源緩存在memory cache 或 disk cache中。

          第二次請求時,瀏覽器判斷請求參數,如果符合強緩存條件就直接返回狀態碼200,從本地緩存中拿數據。否則把響應參數存在request header請求頭中,看是否符合協商緩存,符合則返回狀態碼304,不符合則服務器會返回全新資源。

          Expires:

          這是 http1.0 時的規范;它的值為一個絕對時間的GMT格式的時間字符串,如Mon, 10 Jun 2022 21: 31 :12 GMT,如果發送請求的時間在expires之前,那么本地緩存始終有效,否則就會發送請求到服務器來獲取資源。

          Expires過度依賴本地時間,如果本地與服務器時間不同步,就會出現資源無法被緩存或者資源永遠被緩存的情況。所以,Expires字段幾乎不被使用了

          cache-control:

          上面我們提到了Expires有個缺點,當客戶端本地時間和服務器時間不一致時會產生誤差,瀏覽器會直接向服務器請求新的資源,為了解決這個問題,在http1.1規范中,提出了cache-control字段,且這個字段優先級高于上面提到的Expires,值是相對時間。

          在cache-control中有常見的幾個響應屬性值,它們分別是:

          • max-age=100 緩存100秒后過期,資源緩存在本地
          • s-maxage 覆蓋 max-age,作用與max-age一樣,但只用于代理服務器中緩存
          • no-cache 不使用本地緩存。使用協商緩存,先與服務器確認返回的響應是否被更改,如果之前的響應中存在ETag,那么請求的時候會與服務端驗證,如果資源未被更改,則可以避免重新下載。
          • no-store 所有內容都不會被緩存,既不使用強制緩存也不適用協商緩存,每次用戶請求該資源,都會向服務器發送一個請求,服務器再返回資源
          • public 可以被所有的用戶緩存,包括客戶端和代理服務器
          • private 只能被客戶端緩存,不允許CDN等中繼緩存服務器對其緩存

          2、協商緩存

          上面提到的強緩存都是由本地瀏覽器在確定是否使用緩存,當瀏覽器沒有命中強緩存時就會向瀏覽器發送請求,驗證協商緩存是否命中,如果緩存命中則返回304狀態碼,否則返回新的資源數據。

          協商緩存(也叫對比緩存)是由服務器來確定資源是否可用,這將涉及到兩組字段成對出現的,在瀏覽器第一次發出請求時會帶上字段(Last-Modified或者Etag),則后續請求則會帶上對于的請求字段(if-modified-since或者if-none-Match),若響應頭沒有Last-Modified或者Etag,則請求頭也不會有對應的字段

          基于Last-Modified:

          1. 首先需要在服務器端讀出文件修改時間,
          2. 將讀出來的修改時間賦給響應頭的last-modified字段。
          3. 最后設置Cache-control:no-cache

          const http = require('http');
          const fs = require('fs');
          http.createServer((req,res)=>{
          if(req.url === 'test.png'){
          const data = fs.readFileSync('./test.png');
          const {mtime} = fs.statSync('./test.png');
          const temp = req.headers['if-modified-since'];
          if(temp === mtime.toUTCString()){
          res.statusCode = 304;
          res.end();
          return;
          }
          res.setHeader('last-modified',mtime.toUTCString());
          res.setHeader('Catch-Control','no=cache');
          res.end(data);
          }else{
          res.end(fs.readFileSync('./test.html'));
          }
          })

          基于ETag:

          1. 第一次請求某資源的時候,服務端讀取文件并計算出文件指紋,將文件指紋放在響應頭的etag字段中跟資源一起返回給客戶端。
          2. 第二次請求某資源的時候,客戶端自動從緩存中讀取出上一次服務端返回的ETag也就是文件指紋。并賦給請求頭的if-None-Match字段,讓上一次的文件指紋跟隨請求一起回到服務端。
          3. 服務端拿到請求頭中的is-None-Match字段值(也就是上一次的文件指紋),并再次讀取目標資源并生成文件指紋,兩個指紋做對比。如果兩個文件指紋完全吻合,說明文件沒有被改變,則直接返回304狀態碼和一個空的響應體并return。如果兩個文件指紋不吻合,則說明文件被更改,那么將新的文件指紋重新存儲到響應頭的ETag中并返回給客戶端
          const http = require('http');
          const fs = require('fs');
          const etag = require('etag');
          http.createServer((req,res)=>{
          if(req.url === 'test.png'){
          const data = fs.readFileSync('./test.png');
          const etagContent = etag(data);
          const noMatch = req.headers['if-none-match'];
          if(noMatch === etagContent){
          res.statusCode = 304;
          res.end();
          return;
          }
          res.setHeader('etag',etagContent);
          res.setHeader('Catch-Control','no=cache');
          res.end(data);
          }else{
          res.end(fs.readFileSync('./test.html'));
          }
          })

          作者簡介

          畢清華:精選主力干將!


          來源:微信公眾號:58本地服務終端技術

          出處:https://mp.weixin.qq.com/s/-83N7RS1B6V_r5tcU2CyrA

          試公司:

          阿里

          面試環節:

          一面

          問題:

          說一說你對瀏覽器強緩存和協商緩存的理解

          答案:

          這里說的緩存是指瀏覽器(客戶端)在本地磁盤中對訪問過的資源保存的副本文件。

          瀏覽器緩存主要有以下幾個優點:

          1. 減少重復數據請求,避免通過網絡再次加載資源,節省流量。
          2. 降低服務器的壓力,提升網站性能。
          3. 加快客戶端加載網頁的速度, 提升用戶體驗。

          瀏覽器緩存分為強緩存和協商緩存,兩者有兩個比較明顯的區別:

          1. 如果瀏覽器命中強緩存,則不需要給服務器發請求;而協商緩存最終由服務器來決定是否使用緩存,即客戶端與服務器之間存在一次通信。
          2. 在 chrome 中強緩存(雖然沒有發出真實的 http 請求)的請求狀態碼返回是 200 (from cache);而協商緩存如果命中走緩存的話,請求的狀態碼是 304 (not modified)。 不同瀏覽器的策略不同,在 Fire Fox 中,from cache 狀態碼是 304.

          其中 from cache 會分為 from disk cache 和 from memory cache. 從內存中獲取最快,但是是 session 級別的緩存,關閉瀏覽器之后就沒有了。

          請求流程

          瀏覽器在第一次請求后緩存資源,再次請求時,會進行下面兩個步驟:

          1. 瀏覽器會獲取該緩存資源的 header 中的信息,根據 response header 中的 expires 和 cache-control 來判斷是否命中強緩存,如果命中則直接從緩存中獲取資源。
          2. 如果沒有命中強緩存,瀏覽器就會發送請求到服務器,這次請求會帶上 IF-Modified-Since 或者 IF-None-Match, 它們的值分別是第一次請求返回 Last-Modified 或者 Etag,由服務器來對比這一對字段來判斷是否命中。如果命中,則服務器返回 304 狀態碼,并且不會返回資源內容,瀏覽器會直接從緩存獲取;否則服務器最終會返回資源的實際內容,并更新 header 中的相關緩存字段。

          借用網上的一張圖片

          強緩存

          強緩存是根據返回頭中的 Expires 或者 Cache-Control 兩個字段來控制的,都是表示資源的緩存有效時間。

          • Expires 是 http 1.0 的規范,值是一個GMT 格式的時間點字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT 。這個時間點代表資源失效的時間,如果當前的時間戳在這個時間之前,則判定命中緩存。有一個缺點是,失效時間是一個絕對時間,如果服務器時間與客戶端時間偏差較大時,就會導致緩存混亂。而服務器的時間跟用戶的實際時間是不一樣是很正常的,所以 Expires 在實際使用中會帶來一些麻煩。
          • Cache-Control 這個字段是 http 1.1 的規范,一般常用該字段的 max-age 值來進行判斷,它是一個相對時間,比如 .Cache-Control:max-age=3600 代表資源的有效期是 3600 秒。并且返回頭中的 Date 表示消息發送的時間,表示當前資源在 Date ~ Date +3600s 這段時間里都是有效的。不過我在實際使用中常常遇到設置了 max-age 之后,在 max-age 時間內重新訪問資源卻會返回 304 not modified ,這是由于服務器的時間與本地的時間不同造成的。當然 Cache-Control 還有其他幾個值可以設置, 不過相對來說都很少用了:no-cache 不使用本地緩存。需要使用協商緩存。no-store直接禁止瀏覽器緩存數據,每次請求資源都會向服務器要完整的資源, 類似于 network 中的 disabled cache。public 可以被所有用戶緩存,包括終端用戶和 cdn 等中間件代理服務器。private 只能被終端用戶的瀏覽器緩存。

          如果 Cache-Control 與 Expires 同時存在的話, Cache-Control 的優先級高于 Expires 。

          協商緩存

          協商緩存是由服務器來確定緩存資源是否可用。 主要涉及到兩對屬性字段,都是成對出現的,即第一次請求的響應頭帶上某個字, Last-Modified 或者 Etag,則后續請求則會帶上對應的請求字段 If-Modified-Since或者 If-None-Match,若響應頭沒有 Last-Modified 或者 Etag 字段,則請求頭也不會有對應的字段。

          • Last-Modified/If-Modified-Since 二者的值都是GMT格式的時間字符串, Last-Modified 標記最后文件修改時間, 下一次請求時,請求頭中會帶上 If-Modified-Since 值就是 Last-Modified 告訴服務器我本地緩存的文件最后修改的時間,在服務器上根據文件的最后修改時間判斷資源是否有變化, 如果文件沒有變更則返回 304 Not Modified ,請求不會返回資源內容,瀏覽器直接使用本地緩存。當服務器返回 304 Not Modified 的響應時,response header 中不會再添加的 Last-Modified 去試圖更新本地緩存的 Last-Modified, 因為既然資源沒有變化,那么 Last-Modified 也就不會改變;如果資源有變化,就正常返回返回資源內容,新的 Last-Modified 會在 response header 返回,并在下次請求之前更新本地緩存的 Last-Modified,下次請求時,If-Modified-Since會啟用更新后的 Last-Modified。
          • Etag/If-None-Match, 值都是由服務器為每一個資源生成的唯一標識串,只要資源有變化就這個值就會改變。服務器根據文件本身算出一個哈希值并通過 ETag字段返回給瀏覽器,接收到 If-None-Match 字段以后,服務器通過比較兩者是否一致來判定文件內容是否被改變。與 Last-Modified 不一樣的是,當服務器返回 304 Not Modified 的響應時,由于在服務器上ETag 重新計算過,response header中還會把這個 ETag 返回,即使這個 ETag 跟之前的沒有變化。

          HTTP中并沒有指定如何生成 ETag,可以由開發者自行生成,哈希是比較理想的選擇。

          為什么要有 Etag

          HTTP1.1 中 Etag 的出現主要是為了解決幾個 Last-Modified 比較難解決的問題:

          • 一些文件也許會周期性的更改,但是內容并不改變(僅僅改變的修改時間),這個時候我們并不希望客戶端認為這個文件被修改了,而重新GET;
          • 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since 能檢查到的粒度是秒級的,使用 Etag 就能夠保證這種需求下客戶端在1秒內能刷新 N 次 cache。
          • 某些服務器不能精確的得到文件的最后修改時間。

          優先級

          Cache-Control > expires > Etag > Last-Modified

          用戶行為對緩存的影響

          經過對qq、fire fox 、safari 、chrome 這幾個瀏覽器的訪問同一個頁面測試我發現,不同的瀏覽器在 F5 刷新的時候 ,同一個文件 qq 、fire fox 瀏覽器會返回 304 Not Nodified,在請求頭中不攜帶 Expires/Cache-Control; 而 chrome 和 safari 刷新的時候,會返回 200 from cache, 沒有真正發起請求,走強緩存。可見不同的瀏覽器反饋是不一致的,所以下面表格中"F5刷新"時 Expires/Cache-Control 會無效我認為是存在一定爭議的。

          而 Ctrl + F5 強制刷新的時候,會暫時禁用強緩存和協商緩存。

          如何設置強緩存和協商緩存

          1. 后端服務器,寫入代碼邏輯中:res.setHeader('max-age': '3600 public') res.setHeader(etag: '5c20abbd-e2e8') res.setHeader('last-modified': Mon, 24 Dec 2018 09:49:49 GMT)
          2. Nginx 配置add_header Cache-Control "max-age=3600" 一般來說,通過 nginx 靜態資源服務器,會默認給資源帶上強緩存、協商緩存的 header 字段。

          兩個示例

          1. 如果在 cache-control 定義的 max-age 時間之內,js, css 文件會走強緩存,http 狀態碼是 200, 跟服務器也并不會有交互。但是第一個文件 index.html 文件, 每次回車或者刷新都是狀態碼都是 304 ,因為它的請求頭中默認每次都攜帶了 Cache-Control: max-age=0 。

          1. js css 文件 cache-control 超時之后,重新按回車會走協商緩存,請求服務器發現資源沒有改變,于是返回 304 ,瀏覽器從緩存中獲取內容,從 size 中也可以看出端倪, 幾百 B 的包不是靜態資源的體積。

          三級緩存原理(大白話)

          最后總結一下瀏覽器的三級緩存原理:

          1. 先去內存看,如果有,直接加載
          2. 如果內存沒有,擇取硬盤獲取,如果有直接加載
          3. 如果硬盤也沒有,那么就進行網絡請求
          4. 加載到的資源緩存到硬盤和內存

          原文:https://github.com/frontend9/fe9-interview/issues/29


          主站蜘蛛池模板: 亚洲av无码一区二区乱子伦as| 78成人精品电影在线播放日韩精品电影一区亚洲 | 亚洲欧洲无码一区二区三区| 九九久久99综合一区二区| 三上悠亚一区二区观看| 国产视频一区二区在线播放| 国产视频一区在线播放| 久久久久人妻一区精品果冻| 精品无码国产一区二区三区51安 | 色婷婷av一区二区三区仙踪林| 亚洲AV无码第一区二区三区| 中文字幕一区二区区免| 日本一区二区三区不卡视频中文字幕| aⅴ一区二区三区无卡无码| 亚洲综合色自拍一区| 日本片免费观看一区二区| 无码夜色一区二区三区| 久久精品免费一区二区| 蜜桃无码一区二区三区| 中文字幕日韩一区二区三区不卡| 国产在线一区二区| 亚洲AV无一区二区三区久久| 国产精品一区二区久久不卡| 成人区精品人妻一区二区不卡| 国产福利电影一区二区三区,免费久久久久久久精 | 福利一区国产原创多挂探花| 国精产品一区一区三区| 在线观看免费视频一区| 国产亚洲福利精品一区| 精品一区二区在线观看| 日韩国产精品无码一区二区三区 | 午夜视频久久久久一区| 合区精品久久久中文字幕一区| 无码日韩人妻AV一区免费l | 日韩一区二区三区无码影院| 亚洲一区二区三区免费观看| 伊人久久精品一区二区三区| 国产精品一区二区AV麻豆| 538国产精品一区二区在线| 伊人久久精品无码av一区| 91久久精品无码一区二区毛片|