2021-12-08 瀏覽器常用緩存策略及vue-cli單頁(yè)面SPA應(yīng)用緩存優(yōu)化

問(wèn)題描述

vue 項(xiàng)目打包上線之后枕屉,每一次都會(huì)有瀏覽器緩存問(wèn)題啤咽,需要手動(dòng)的清除緩存。這樣用戶(hù)體驗(yàn)非常不好穿稳,所以我們?cè)诖虬渴鸬臅r(shí)候需要盡量避免瀏覽器的緩存。

需要解決的問(wèn)題

1晌坤、程序每次升級(jí)后逢艘,用戶(hù)都不會(huì)因?yàn)榫彺鎲?wèn)題而執(zhí)行的仍然是老的程序。
2泡仗、若程序沒(méi)升級(jí)埋虹,用戶(hù)對(duì)靜態(tài)資源的請(qǐng)求則能用到緩存。

關(guān)于瀏覽器緩存策略娩怎,可以分為這三種:

  • (1)不使用緩存

no-store
永遠(yuǎn)都不在客戶(hù)端存儲(chǔ)資源搔课,永遠(yuǎn)都去原始服務(wù)器去獲取資源。

  • (2)強(qiáng)制使用緩存

private(ngnix默認(rèn)): 只能被終端用戶(hù)的瀏覽器緩存截亦,不允許CDN等中繼緩存服務(wù)器對(duì)其緩存, 只有在第一次請(qǐng)求的時(shí)候才訪問(wèn)服務(wù)器, 若有max-age, 則緩存期間不訪問(wèn)服務(wù)器獲取資源爬泥,過(guò)期后才訪問(wèn)。

public: 可以被所有的用戶(hù)緩存崩瓤,包括終端用戶(hù)和CDN等中間代理服務(wù)器袍啡。

  • (3)協(xié)商使用緩存

no-cache
可以在客戶(hù)端存儲(chǔ)資源,不管本地緩存是否過(guò)期却桶,每次都必須去服務(wù)端做新鮮度校驗(yàn)境输,來(lái)決定從服務(wù)端獲取新的資源(200)還是使用客戶(hù)端緩存(304)。也就是所謂的協(xié)商緩存颖系。

must-revalidate
可以在客戶(hù)端存儲(chǔ)資源嗅剖,只有本地緩存過(guò)期才去服務(wù)端做新鮮度校驗(yàn)。

1嘁扼、不使用緩存

有時(shí)信粮,我們希望瀏覽器永遠(yuǎn)都不要使用緩存,全部到服務(wù)器拉取數(shù)據(jù)趁啸,此時(shí)即為不使用緩存强缘,我們可以在服務(wù)端通過(guò)Cache-Control為 no-store實(shí)現(xiàn)。


服務(wù)器端針對(duì)上面文件設(shè)置了no-store不傅,可以看到在請(qǐng)求的時(shí)候旅掂,無(wú)論怎么刷新,都是返回200访娶,不會(huì)顯示304商虐,也不會(huì)顯示“memory cache”或“disk cache”,說(shuō)明真的都是從服務(wù)器重新拉取數(shù)據(jù)。

比如我們想設(shè)置html文件不緩存称龙,可以在域名的解析配置中如下設(shè)置,當(dāng)文件后綴為html或htm時(shí)add_header Cache-Control “no-store”

server {
listen 80;
server_name yourdomain.com;
location / {
    try_files $uri $uri/ /index.html;
    root /yourdir/;
    index index.html index.htm;

    if ($request_filename ~* .*\.(?:htm|html)$)
    {
        add_header Cache-Control "no-store";  //對(duì)html文件設(shè)置永遠(yuǎn)不緩存
    }  
  }
}

這種方式缺點(diǎn)就是每次都要去服務(wù)端拉取文件戳晌,即使文件沒(méi)有更新鲫尊,很明顯這樣增加了不必要的帶寬消耗。

如果文件沒(méi)有更新沦偎,我們就使用緩存疫向,只有更新了才去拉取最新文件,這樣多好豪嚎,這就是協(xié)商緩存搔驼。

2、協(xié)商緩存

協(xié)商緩存就是瀏覽器攜帶文件緩存標(biāo)識(shí)(如Last-Modified或ETag)侈询,向服務(wù)器發(fā)送請(qǐng)求舌涨,由服務(wù)器根據(jù)文件緩存標(biāo)識(shí)來(lái)決定是否使用緩存,如果文件沒(méi)有更新扔字,則告訴瀏覽器使用本地緩存囊嘉,如果文件更新了,則直接返回新文件內(nèi)容革为。
可以在服務(wù)端通過(guò)設(shè)置Cache-Control為 no-cache或者max-age=0來(lái)實(shí)現(xiàn)

可以看出扭粱,相比不使用緩存,協(xié)商緩存是會(huì)大大減少帶寬消耗的震檩。

  • 協(xié)商緩存生效琢蛤,返回304 和 Not Modified
  • 協(xié)商緩存無(wú)效,返回200和請(qǐng)求文件
image.png

我們?cè)跒g覽器調(diào)試頁(yè)面抛虏,可以看到有304的博其,即是使用了協(xié)商緩存

服務(wù)器返回的header中會(huì)有Last-Modified和ETag標(biāo)識(shí),而瀏覽器請(qǐng)求header中會(huì)包含If-Modified-Since和If-None-Match

LAST-MODIFIED和IF-MODIFIED-SINCE

在 http 1.0 版本中嘉蕾,第一次請(qǐng)求資源時(shí)服務(wù)器通過(guò) Last-Modified 來(lái)設(shè)置響應(yīng)頭的緩存標(biāo)識(shí)贺奠,并且把資源最后修改的時(shí)間作為值填入,然后將資源返回給瀏覽器错忱。在第二次請(qǐng)求時(shí)儡率,瀏覽器會(huì)首先帶上 If-Modified-Since 請(qǐng)求頭去訪問(wèn)服務(wù)器,服務(wù)器會(huì)將 If-Modified-Since 中攜帶的時(shí)間與資源修改的時(shí)間匹配以清,如果時(shí)間不一致儿普,服務(wù)器會(huì)返回新的資源,并且將 Last-Modified 值更新掷倔,作為響應(yīng)頭返回給瀏覽器眉孩。如果時(shí)間一致,表示資源沒(méi)有更新,服務(wù)器返回 304 狀態(tài)碼浪汪,瀏覽器拿到響應(yīng)狀態(tài)碼后從本地緩存數(shù)據(jù)庫(kù)中讀取緩存資源巴柿。

這種方式有2個(gè)弊端,第一個(gè)就是當(dāng)服務(wù)器中的資源增加了一個(gè)字符死遭,后來(lái)又把這個(gè)字符刪掉广恢,本身資源文件并沒(méi)有發(fā)生變化,但修改時(shí)間發(fā)生了變化呀潭。當(dāng)下次請(qǐng)求過(guò)來(lái)時(shí)钉迷,服務(wù)器也會(huì)把這個(gè)本來(lái)沒(méi)有變化的資源重新返回給瀏覽器;第二個(gè)就是修改時(shí)間的單位為秒钠署,所以存在1s的間隙糠聪,即使更新了,也會(huì)認(rèn)為沒(méi)有更新谐鼎。

ETAG和IF-NONE-MATCH

在 http 1.1 版本中舰蟆,服務(wù)器通過(guò) Etag 來(lái)設(shè)置響應(yīng)頭緩存標(biāo)識(shí)。Etag 的值由服務(wù)端生成狸棍,可以認(rèn)為是文件內(nèi)容的hash值夭苗。在第一次請(qǐng)求時(shí),服務(wù)器會(huì)將資源和 Etag 一并返回給瀏覽器隔缀,瀏覽器將兩者緩存到本地緩存數(shù)據(jù)庫(kù)题造。在第二次請(qǐng)求時(shí),瀏覽器會(huì)將 Etag 信息放到 If-None-Match 請(qǐng)求頭去訪問(wèn)服務(wù)器猾瘸,服務(wù)器收到請(qǐng)求后界赔,會(huì)將服務(wù)器中的文件標(biāo)識(shí)與瀏覽器發(fā)來(lái)的標(biāo)識(shí)進(jìn)行對(duì)比,如果不相同牵触,服務(wù)器返回更新的資源和新的 Etag 淮悼,如果相同,服務(wù)器返回 304 狀態(tài)碼揽思,瀏覽器讀取緩存

兩者對(duì)比

  • 首先在精確度上袜腥,Etag要優(yōu)于Last-Modified。Last-Modified的時(shí)間單位是秒钉汗,如果某個(gè)文件在1秒內(nèi)改變了多次羹令,那么他們的Last-Modified其實(shí)并沒(méi)有體現(xiàn)出來(lái)修改,但是Etag每次都會(huì)改變確保了精度损痰;如果是負(fù)載均衡的服務(wù)器福侈,各個(gè)服務(wù)器生成的Last-Modified也有可能不一致。

  • 第二在性能上卢未,Etag要遜于Last-Modified肪凛,畢竟Last-Modified只需要記錄時(shí)間堰汉,而Etag需要服務(wù)器通過(guò)算法來(lái)計(jì)算出一個(gè)hash值。

  • 第三在優(yōu)先級(jí)上伟墙,服務(wù)器校驗(yàn)優(yōu)先考慮Etag

3翘鸭、強(qiáng)制緩存

有時(shí)我們希望文件強(qiáng)制使用緩存,比如通過(guò)vue-cli產(chǎn)生的js和css戳葵,文件名上帶有hash值矮固,所以如果文件名沒(méi)有變的時(shí)候,我們希望文件永久緩存譬淳,這樣可以減少網(wǎng)絡(luò)請(qǐng)求。

強(qiáng)制緩存整體流程比較簡(jiǎn)單盹兢,就是在第一次訪問(wèn)服務(wù)器取到數(shù)據(jù)之后邻梆,在過(guò)期時(shí)間之內(nèi)不會(huì)再去重復(fù)請(qǐng)求。實(shí)現(xiàn)這個(gè)流程的核心就是如何知道當(dāng)前時(shí)間是否超過(guò)了過(guò)期時(shí)間绎秒。

強(qiáng)制緩存的過(guò)期時(shí)間通過(guò)第一次訪問(wèn)服務(wù)器時(shí)返回的響應(yīng)頭獲取浦妄。在 http 1.0 和 http 1.1 版本中通過(guò)不同的響應(yīng)頭字段實(shí)現(xiàn)。

在 http 1.0 版本中见芹,強(qiáng)制緩存通過(guò) Expires 響應(yīng)頭來(lái)實(shí)現(xiàn)剂娄。 expires 表示未來(lái)資源會(huì)過(guò)期的時(shí)間。也就是說(shuō)玄呛,當(dāng)發(fā)起請(qǐng)求的時(shí)間超過(guò)了 expires 設(shè)定的時(shí)間阅懦,即表示資源緩存時(shí)間到期,會(huì)發(fā)送請(qǐng)求到服務(wù)器重新獲取資源徘铝。而如果發(fā)起請(qǐng)求的時(shí)間在 expires 限定的時(shí)間之內(nèi)耳胎,瀏覽器會(huì)直接讀取本地緩存數(shù)據(jù)庫(kù)中的信息(from memory or from disk),兩種方式根據(jù)瀏覽器的策略隨機(jī)獲取惕它。

在 http 1.1 版本中怕午,可以設(shè)置Cache-Control中的 max-age=xxx ,來(lái)表示緩存的資源將在 xxx 秒后過(guò)期淹魄。一般來(lái)說(shuō)郁惜,為了兼容,兩個(gè)版本的強(qiáng)制緩存都會(huì)被實(shí)現(xiàn)甲锡。

為什么有了Expires兆蕉,后來(lái)又增加了max-age呢,這是因?yàn)镋xpires是一個(gè)絕對(duì)時(shí)間缤沦,有可能客戶(hù)端的時(shí)間和服務(wù)器不一致恨樟,導(dǎo)致緩存不能按照預(yù)期進(jìn)行,而max-age則是個(gè)相對(duì)時(shí)間疚俱,比如3600s劝术,自瀏覽器請(qǐng)求后3600s之內(nèi),都使用本地緩存,和客戶(hù)端的時(shí)間沒(méi)關(guān)系养晋。

補(bǔ)充:

緩存的優(yōu)先級(jí)策略

  • 文件緩存位置:
    Service Worker 瀏覽器背后的獨(dú)立線程緩存
    Memory Cache 瀏覽器內(nèi)存緩存
    Disk Cache 系統(tǒng)硬盤(pán)緩存
    Push Cache 推送緩存

具體可以看這里:
https://blog.csdn.net/weixin_43972437/article/details/105513486

打開(kāi)網(wǎng)頁(yè)衬吆,地址欄輸入地址:
查找 disk cache 中是否有匹配。如有則使用绳泉;如沒(méi)有則發(fā)送網(wǎng)絡(luò)請(qǐng)求逊抡。

普通刷新 (F5):
因?yàn)轫?yè)面tab并沒(méi)有關(guān)閉,因此 memory cache 是可用的零酪,會(huì)被優(yōu)先使用(如果匹配的話)冒嫡。其次才是 disk cache。

強(qiáng)制刷新 (Ctrl + F5):
瀏覽器不使用緩存四苇,因此發(fā)送的請(qǐng)求頭部均帶有 Cache-control: no-cache(為了兼容孝凌,還帶了 Pragma: no-cache)。服務(wù)器直接返回 200 和最新內(nèi)容月腋。

比如:訪問(wèn)圖片-> 200 -> 退出瀏覽器
再進(jìn)來(lái)-> 200(from disk cache) -> 刷新 -> 200(from memory cache)

  • 緩存失效策略分類(lèi):
    緩存過(guò)期時(shí)間 : Cache-control 的優(yōu)先級(jí)高于 Expires
    文件是否改動(dòng)標(biāo)識(shí): Etag 的優(yōu)先級(jí)高于 Last-Modified

SPA應(yīng)用緩存解決方案

  • 方案一:直接在index.html中加入了這幾行代碼:
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">

缺點(diǎn):升級(jí)時(shí)緩存問(wèn)題倒解決了蟀架,但直接導(dǎo)致了用戶(hù)每次訪問(wèn)你的程序時(shí)都要重新請(qǐng)求服務(wù)器,所有的靜態(tài)資源都無(wú)法用緩存了榆骚,浪費(fèi)流量片拍,網(wǎng)絡(luò)壓力變大。且多數(shù)服務(wù)器不支持妓肢。

  • 方案二:Nginx 配合 vue.config.js 進(jìn)行配置

由于打包后的js捌省、css和圖片,一般名稱(chēng)都帶有hash值碉钠,名稱(chēng)中的hash變了所禀,自然會(huì)拉取新文件,所以我們可以將這類(lèi)文件設(shè)置為強(qiáng)制緩存放钦,只要文件名不變色徘,就一直緩存,或者設(shè)置緩存比較久的時(shí)間100天或者一年操禀。

而html文件則不能設(shè)為強(qiáng)制緩存褂策,一般html名稱(chēng)是沒(méi)法帶hash值的,所以html如果設(shè)置了強(qiáng)制緩存颓屑,則永遠(yuǎn)也沒(méi)法更新斤寂,html不更新,其引用的js揪惦、css等名稱(chēng)也不會(huì)更新遍搞,則整個(gè)服務(wù)都沒(méi)有更新,只能讓用戶(hù)清除緩存了器腋。所以針對(duì)html文件溪猿,我們可以設(shè)置協(xié)商緩存或者直接不使用緩存钩杰。

nginx配置:

location /udaam-ui {
       root  /usr/local/ui-workspace;
       index index.html index.htm;
       try_files $uri $uri/ /udaam-ui/index.html;
       if ($request_filename ~* .*\.(js|css|woff|png|jpg|jpeg)$){
            expires    100d;  #js、css诊县、圖片緩存100天
            #add_header Cache-Control "max-age = 8640000"; #或者設(shè)置max-age
        }
        if ($request_filename ~* .*\.(?:htm|html)$){
            add_header Cache-Control "no-cache, no-store";  #html不緩存
        }
}

root:設(shè)置靜態(tài)根目錄為 data
index:設(shè)置目錄的默認(rèn)文件為 index.html 讲弄、index.htm
try_files:設(shè)置文件查找規(guī)則為 uriuri/ /index.html。即3個(gè)規(guī)則依痊,先從 uri 查找避除,再?gòu)? mathimg=uri/ 目錄中查找,最后查找 /index.html胸嘁。

vue.config.js設(shè)置:
修改output的filename和chunkFilename

 configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      return {
        output: {
            // 輸出重構(gòu)  打包編譯后的 文件名稱(chēng)  【模塊名稱(chēng).版本號(hào).時(shí)間戳】
          filename: `js/[name].[chunkhash].js`,
          chunkFilename: `js/[id].[chunkhash].js`
        }
      }
    }
  },
  • filename 指列在entry 中瓶摆,打包后輸出的文件的名稱(chēng)。
  • chunkFilename 指未列在entry 中性宏,卻又需要被打包出來(lái)的文件的名稱(chēng)群井。

修改打包后的css

  css: {
    extract: { // 打包后css文件名稱(chēng)添加時(shí)間戳
      filename: `css/[name].[chunkhash].css`,
      chunkFilename: `css/chunk.[id].[chunkhash].css`
    }
  }

原文地址:https://blog.csdn.net/qq_42268364/article/details/119386473
參考文章:http://www.reibang.com/p/5068788204f9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衔沼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昔瞧,老刑警劉巖指蚁,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異自晰,居然都是意外死亡凝化,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)酬荞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搓劫,“玉大人,你說(shuō)我怎么就攤上這事混巧∏瓜颍” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵咧党,是天一觀的道長(zhǎng)秘蛔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)傍衡,這世上最難降的妖魔是什么深员? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮蛙埂,結(jié)果婚禮上倦畅,老公的妹妹穿的比我還像新娘。我一直安慰自己绣的,他們只是感情好叠赐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布欲账。 她就那樣靜靜地躺著,像睡著了一般燎悍。 火紅的嫁衣襯著肌膚如雪敬惦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天谈山,我揣著相機(jī)與錄音俄删,去河邊找鬼。 笑死奏路,一個(gè)胖子當(dāng)著我的面吹牛畴椰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸽粉,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼斜脂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了触机?” 一聲冷哼從身側(cè)響起帚戳,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎儡首,沒(méi)想到半個(gè)月后片任,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔬胯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年对供,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氛濒。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡产场,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舞竿,到底是詐尸還是另有隱情京景,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布骗奖,位于F島的核電站醋粟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏重归。R本人自食惡果不足惜米愿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鼻吮。 院中可真熱鬧育苟,春花似錦、人聲如沸椎木。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至漱竖,卻和暖如春禽篱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背馍惹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工躺率, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人万矾。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓悼吱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親良狈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子后添,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容