網(wǎng)站CSS、js更新后客戶瀏覽器緩存問(wèn)題、需要刷新才能正確顯示的解決方案。
前端開(kāi)發(fā)中可能出現(xiàn)的問(wèn)題,更新了在線項(xiàng)目,用戶的瀏覽器顯示了上一頁(yè),我們沒(méi)有及時(shí)獲取更新的資源,這是為什么?為什么此時(shí)用戶刷新頁(yè)面可以獲得更新的資源?
答案是瀏覽器緩存
瀏覽器緩存是前端優(yōu)化的重要問(wèn)題,緩存提供了很多好處。
(1)減少冗馀數(shù)據(jù)傳輸,節(jié)省帶寬。
(2)減輕服務(wù)器的請(qǐng)求負(fù)擔(dān),如果有緩存,可以少向服務(wù)器發(fā)送請(qǐng)求。尤其是對(duì)訪問(wèn)量大的一些網(wǎng)站來(lái)說(shuō),更為重要。
(3)資源從緩存中讀取,無(wú)需向服務(wù)器發(fā)送請(qǐng)求和等待返回,從而加快客戶端訪問(wèn)速度。
但是緩存同樣給前端帶來(lái)了一個(gè)很?chē)?yán)重的問(wèn)題,就是上面所說(shuō)的項(xiàng)目更新的問(wèn)題。如果項(xiàng)目更新了,但是用戶訪問(wèn)時(shí)瀏覽器讀取的是緩存資源,那么用戶就獲取不到最新的頁(yè)面,影響用戶使用。
接下來(lái)就從瀏覽器緩存開(kāi)始分析出現(xiàn)項(xiàng)目更新問(wèn)題的原因,并給出相應(yīng)的解決方法。
瀏覽器緩存主要指http緩存,其機(jī)制是根據(jù)http報(bào)文的緩存標(biāo)識(shí)進(jìn)行相應(yīng)操作。
一、http狀態(tài)碼
在討論瀏覽器緩存之前,我們先看看網(wǎng)頁(yè)相關(guān)的http狀態(tài)碼,打開(kāi)控制臺(tái),在Network下捕捉請(qǐng)求,注意Status和Size欄,會(huì)看到200 from disk cache,200數(shù)值大小。
刷新頁(yè)面,會(huì)看到,304 數(shù)值大小,200 from memory cache。
這幾個(gè)有什么不同呢?200和304是常見(jiàn)的兩個(gè)http狀態(tài)碼,200表示文件發(fā)生改動(dòng),304表示文件未改動(dòng),都是服務(wù)器返回告知的。在上面兩張圖中,我們注意到,有些200是灰色的,灰色的200表示沒(méi)有向服務(wù)器發(fā)送請(qǐng)求,而是直接從緩存中讀取。從緩存中讀取又分為從內(nèi)存(from memory cache)中讀取還是從磁盤(pán)中讀?。╢rom disk cache)。
總結(jié)一張表。
200 from memory cache | 狀態(tài)碼是灰色的,從內(nèi)存中讀取之前已經(jīng)加載過(guò)的資源,不請(qǐng)求服務(wù)器,頁(yè)面關(guān)閉時(shí),資源就會(huì)被內(nèi)存釋放,再次打開(kāi)相同頁(yè)面不會(huì)出現(xiàn)此類(lèi)情況,在同一頁(yè)面刷新才會(huì)出現(xiàn)。一般腳本、字體、圖片會(huì)存在內(nèi)存當(dāng)中 |
200 from disk cache | 狀態(tài)碼是灰色的,從磁盤(pán)中讀取之前已經(jīng)加載過(guò)的資源,不請(qǐng)求服務(wù)器,頁(yè)面關(guān)閉不會(huì)被釋放,這部分資源存在電腦磁盤(pán)里,只有用戶手動(dòng)清除瀏覽器緩存的時(shí)候才會(huì)釋放。一般非腳本會(huì)存在內(nèi)存當(dāng)中,如css等 |
200 數(shù)值大小 | 從服務(wù)器下載最新資源,數(shù)值是從服務(wù)器獲取的全部資源大小 |
304 數(shù)值大小 | 訪問(wèn)服務(wù)器,發(fā)現(xiàn)資源沒(méi)有更新,使用本地資源。數(shù)值是與服務(wù)器通信報(bào)文的大小,并不是資源本身的大小。 |
瀏覽器有三級(jí)緩存原理
1、先查找內(nèi)存,如果內(nèi)存中存在,從內(nèi)存中加載;
2、如果內(nèi)存中未查找到,選擇硬盤(pán)獲取,如果硬盤(pán)中有,從硬盤(pán)中加載;
3、如果硬盤(pán)中未查找到,那就進(jìn)行網(wǎng)絡(luò)請(qǐng)求,加載到的資源緩存到硬盤(pán)和內(nèi)存;
結(jié)合我們的問(wèn)題,假設(shè)某個(gè)用戶打開(kāi)過(guò)我們的頁(yè)面,然后我們更新了文件,用戶再去訪問(wèn),資源加載情況是200 from disk cache,瀏覽器根本沒(méi)有請(qǐng)求服務(wù)器,所以拿不到新的資源文件。那么,有沒(méi)有辦法解決這種情況?瀏覽器緩存機(jī)制是什么樣的?
二、瀏覽器緩存
瀏覽器緩存分兩種:強(qiáng)制緩存和協(xié)商緩存(對(duì)比緩存)
1、強(qiáng)制緩存
強(qiáng)制緩存就是,用戶第一次訪問(wèn)頁(yè)面之后,瀏覽器將數(shù)據(jù)存在緩存中,在過(guò)期時(shí)間之內(nèi),都不會(huì)再請(qǐng)求服務(wù)器。是否使用強(qiáng)制緩存在于資源是否過(guò)期,該過(guò)期時(shí)間從第一次請(qǐng)求的服務(wù)器響應(yīng)頭中獲取。如果在過(guò)期時(shí)間內(nèi),從緩存中讀取,如果超出過(guò)期時(shí)間,則使用協(xié)商緩存(下面會(huì)講)。
控制強(qiáng)制緩存的字段分別是Expires和Cache-Control,其中Cache-Control優(yōu)先級(jí)比Expires高。
上面的200 from memory cache和200 from disk cache屬于強(qiáng)制緩存。
2、協(xié)商緩存
協(xié)商緩存,從字面意思,就是要協(xié)商,是瀏覽器和服務(wù)器協(xié)商,那么瀏覽器每次都要和服務(wù)器通信。在第一次請(qǐng)求服務(wù)器時(shí),服務(wù)器會(huì)返回資源,并且返回一個(gè)資源的緩存標(biāo)識(shí),一起存到瀏覽器的緩存數(shù)據(jù)庫(kù)。當(dāng)?shù)诙握?qǐng)求資源時(shí),瀏覽器會(huì)首先將緩存標(biāo)識(shí)發(fā)送給服務(wù)器,服務(wù)器拿到標(biāo)識(shí)后判斷標(biāo)識(shí)是否匹配,如果不匹配,表示資源有更新,服務(wù)器會(huì)將新數(shù)據(jù)和新的緩存標(biāo)識(shí)一起返回到瀏覽器;如果緩存標(biāo)識(shí)匹配,表示資源沒(méi)有更新,并且返回 304 狀態(tài)碼,瀏覽器就讀取本地緩存服務(wù)器中的數(shù)據(jù)。
與協(xié)商緩存有關(guān)的字段是Last-Modified/IF-Modified-Since、Etag/IF-None-Match。
Last-Modified與ETag是可以一起使用的,服務(wù)器會(huì)優(yōu)先驗(yàn)證ETag,一致的情況下,才會(huì)繼續(xù)比對(duì)Last-Modified,最后才決定是否返回304。
強(qiáng)制緩存和協(xié)商緩存的具體參數(shù)及分析比較可以參考以下文章
再回到我們的問(wèn)題,用戶打開(kāi)瀏覽器發(fā)現(xiàn)是舊的資源,于是手動(dòng)刷新了一下頁(yè)面,得到了新的資源,這是為什么呢?
3、用戶行為會(huì)對(duì)緩存產(chǎn)生影響
結(jié)合上面的內(nèi)容,我們可以分析情況了
1、用戶第一次訪問(wèn)頁(yè)面——200 數(shù)值大小,與服務(wù)器通信,服務(wù)器返回全部資源大小,瀏覽器把獲取到的數(shù)據(jù)根據(jù)緩存規(guī)則進(jìn)行緩存。
2、更新項(xiàng)目,用戶打開(kāi)頁(yè)面是舊的資源——200 from disk cache,命中強(qiáng)緩存,使用了本地緩存,沒(méi)有請(qǐng)求服務(wù)器
3、用戶手動(dòng)刷新頁(yè)面,得到新資源——200 數(shù)值大小,用戶刷新,強(qiáng)緩存失效,使用協(xié)商緩存,根據(jù)緩存標(biāo)識(shí)發(fā)現(xiàn)資源修改了,服務(wù)器返回全部新資源和緩存標(biāo)識(shí)
4、用戶再刷新頁(yè)面——304 數(shù)值大小,協(xié)商緩存,資源沒(méi)有修改,數(shù)值不是全部資源大小,是報(bào)文信息大小。同時(shí),這里會(huì)出現(xiàn)一些資源200 from memory的情況,它們存在內(nèi)存中。
我們?cè)倏磶讖垐D應(yīng)該就很好理解了
三、解決方法
明白了問(wèn)題所在,我們接下來(lái)就可以提出對(duì)應(yīng)的解決方法了。
以vue為例,vue在打包的時(shí)候,css和js名字都加了哈希值,所以改動(dòng)后打包生成的js和css是唯一的,頁(yè)面請(qǐng)求的是新資源,不會(huì)有緩存問(wèn)題。但是入口文件index.html會(huì)因?yàn)榫彺嬖斐筛聠?wèn)題,如果我們更新了,但是瀏覽器使用的是緩存,就會(huì)出現(xiàn)問(wèn)題。所以需要對(duì)入口文件設(shè)置不使用強(qiáng)制緩存,需要每次去服務(wù)器驗(yàn)證文件是否修改,即使用協(xié)商緩存。
使用nginx反向代理,在nginx.conf文件的對(duì)應(yīng)server中設(shè)置,目前我自己實(shí)踐出的可行的一種寫(xiě)法是:
server {
listen 80;
server_name 域名;
root 文件目錄;
index index.html;
location / { // 不加這一句,會(huì)出現(xiàn)nginx歡迎頁(yè)面,無(wú)法正確加載資源
try_files $uri ;
}
location ~ .*\.(html)$ { // 對(duì)html文件限制緩存
add_header Cache-Control no-store; // 不緩存
// 或者用add_header Cache-Control no-cache;替代上面那一句,協(xié)商緩存
add_header Pragma no-cache;
}
}
(1)Cache-Control: no-cache和Cache-Control: no-store區(qū)別
看字面意思容易誤解,no-cache就是不緩存,但是no-cache并不是不緩存,而是使用協(xié)商緩存,所以并不能禁止緩存,no-store才是真正的禁止緩存。從節(jié)省帶寬角度講,使用no-cache更優(yōu)一點(diǎn),文件未發(fā)生改變時(shí)只傳輸很小的報(bào)文大小,只有在文件改變時(shí)才會(huì)傳輸整個(gè)文件大小。而不是no-store不管什么情況都傳輸整個(gè)文件大小。
(2)Pragma: no-cache:和Cache-Control: no-cache區(qū)別
Pragma: no-cache跟Cache-Control: no-cache相同,Pragma: no-cache兼容http 1.0 ,Cache-Control: no-cache是http 1.1提供的。因此,Pragma: no-cache可以應(yīng)用到http 1.0 和http 1.1,而Cache-Control: no-cache只能應(yīng)用于http 1.1.
轉(zhuǎn)自:
1.《為什么uc總是緩存錯(cuò)誤怎么辦看這里!前端項(xiàng)目中 瀏覽器緩存的更新不及時(shí)問(wèn)題及解決方法》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。
2.《為什么uc總是緩存錯(cuò)誤怎么辦看這里!前端項(xiàng)目中 瀏覽器緩存的更新不及時(shí)問(wèn)題及解決方法》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。
3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/gl/3201705.html