迎關(guān)注我的頭條號(hào):Wooola,專注于Java、Golang、微服務(wù)架構(gòu),致力于每天分享原創(chuàng)文章、快樂編碼和開源技術(shù)。
最近發(fā)版前端項(xiàng)目,用戶經(jīng)常反饋新添加功能在線上環(huán)境不好用,常出現(xiàn)新老頁面并存的狀況。經(jīng)前端同事排查法發(fā)現(xiàn),實(shí)際上只需要重新刷新一下頁面就沒事了。但是每次去通知用戶肯定不現(xiàn)實(shí),所以需要對(duì)前端的js和css等文件采取一定的緩存失效的措施,強(qiáng)制瀏覽器重新去服務(wù)器獲取新的js代碼以及css文件。
樓主經(jīng)過實(shí)際的項(xiàng)目情況反饋,總結(jié)以下兩點(diǎn)切實(shí)可行的辦法,分享給大家,希望對(duì)大家有幫助。
時(shí)間版本號(hào)
如果每次發(fā)布,針對(duì)修改過的js或者css文件路徑加上時(shí)間的版本號(hào),一般以年月日拼寫。
<script type="text/javascript" src="lib/common.js?v=20190719"></script> <link rel="stylesheet" type="text/css" href="assets/css/ie/ie8.css?v=20190719" />
如果發(fā)生緊急情況,需要在一天當(dāng)中對(duì)某些css或者js文件多次發(fā)版,可以把時(shí)間精確到時(shí)分秒。
目前樓主主推采用加版本號(hào)的方式,因?yàn)槲募啵荒茏鲈隽啃薷摹:锰幨菦]有做任何修改js或者css文件可以不用加版本號(hào)。
采用隨機(jī)數(shù)
document.write('<script src=\".lib/common.js?r=' + Math.random() + "\"" + '><\/script>');
一般不建議用隨機(jī)數(shù)的方式,因?yàn)槊看嗡⑿马撁妫S機(jī)數(shù)都會(huì)變化,那么瀏覽器認(rèn)為一個(gè)新的url需要重新請(qǐng)求服務(wù)端獲取js或css文件,不會(huì)在使用瀏覽器本地緩存。同時(shí)占用網(wǎng)絡(luò)帶寬,影響服務(wù)器響應(yīng)速度。
可以利用 gulp-rev或者webpack
entry: { main: './src/common.js', slove: './src/ie8.js' }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist') }
例如百度搜索首頁,就是利用hash給js和css文件重命名。
迎關(guān)注我的頭條號(hào):Wooola,專注于Java、Golang、微服務(wù)架構(gòu),致力于每天分享原創(chuàng)文章、快樂編碼和開源技術(shù)。
最近發(fā)版前端項(xiàng)目,用戶經(jīng)常反饋新添加功能在線上環(huán)境不好用,常出現(xiàn)新老頁面并存的狀況。經(jīng)前端同事排查法發(fā)現(xiàn),實(shí)際上只需要重新刷新一下頁面就沒事了。但是每次去通知用戶肯定不現(xiàn)實(shí),所以需要對(duì)前端的js和css等文件采取一定的緩存失效的措施,強(qiáng)制瀏覽器重新去服務(wù)器獲取新的js代碼以及css文件。
樓主經(jīng)過實(shí)際的項(xiàng)目情況反饋,總結(jié)以下兩點(diǎn)切實(shí)可行的辦法,分享給大家,希望對(duì)大家有幫助。
時(shí)間版本號(hào)
如果每次發(fā)布,針對(duì)修改過的js或者css文件路徑加上時(shí)間的版本號(hào),一般以年月日拼寫。
<script type="text/javascript" src="lib/common.js?v=20190719"></script> <link rel="stylesheet" type="text/css" href="assets/css/ie/ie8.css?v=20190719" />
如果發(fā)生緊急情況,需要在一天當(dāng)中對(duì)某些css或者js文件多次發(fā)版,可以把時(shí)間精確到時(shí)分秒。
目前樓主主推采用加版本號(hào)的方式,因?yàn)槲募啵荒茏鲈隽啃薷摹:锰幨菦]有做任何修改js或者css文件可以不用加版本號(hào)。
采用隨機(jī)數(shù)
document.write('<script src=\".lib/common.js?r=' + Math.random() + "\"" + '><\/script>');
一般不建議用隨機(jī)數(shù)的方式,因?yàn)槊看嗡⑿马撁妫S機(jī)數(shù)都會(huì)變化,那么瀏覽器認(rèn)為一個(gè)新的url需要重新請(qǐng)求服務(wù)端獲取js或css文件,不會(huì)在使用瀏覽器本地緩存。同時(shí)占用網(wǎng)絡(luò)帶寬,影響服務(wù)器響應(yīng)速度。
可以利用 gulp-rev或者webpack
entry: { main: './src/common.js', slove: './src/ie8.js' }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist') }
例如百度搜索首頁,就是利用hash給js和css文件重命名。
覽器緩存對(duì)于前端一點(diǎn)都不陌生,最常見的就是,新版本上線了,測(cè)試卻說這怎么還沒有變化呢?使用 ctr + F5 強(qiáng)制刷新之后,立馬就好了。或者清除瀏覽器緩存,按住ctr+shift+delete,彈出如圖:
我們會(huì)發(fā)現(xiàn)目前瀏覽器緩存的圖片和文件的大小。或者進(jìn)入chrome://chrome-urls/找到chrome://cache/ 就可以看到所有緩存的地址列表。對(duì)于瀏覽器緩存,前端對(duì)它是又愛又恨,有時(shí)想保留,有時(shí)想禁掉,所以看看瀏覽器緩存到底是怎樣的?
瀏覽器緩存就是瀏覽器根據(jù) url 第一次訪問網(wǎng)站之后,將網(wǎng)站的 html、css、js、圖片等文件復(fù)制一份保留到瀏覽器中,當(dāng)你二次訪問這個(gè) url 的網(wǎng)站時(shí),如果網(wǎng)站沒有明確表示有更新時(shí),瀏覽器直接在緩存中查找內(nèi)容,不會(huì)再次請(qǐng)求網(wǎng)頁內(nèi)容,只有網(wǎng)頁明確表示有更新時(shí),瀏覽器才會(huì)向服務(wù)器發(fā)起網(wǎng)路請(qǐng)求,再次下載網(wǎng)頁。
如上圖,百度首頁就是使用了緩存機(jī)制,首次訪問之后 web資源被緩存,在后面重復(fù)請(qǐng)求中,資源直接在緩存中讀取,而不是向服務(wù)器請(qǐng)求資源。
2.1、為什么很多網(wǎng)站二次打開速度很快?
網(wǎng)頁二次打開很快,主要原因是第一次加載頁面過程中,緩存了部分耗時(shí)數(shù)據(jù),這一現(xiàn)象,對(duì)于單頁面應(yīng)用開發(fā)非常明顯。
上一篇文章《瀏覽器工作原理》中,瀏覽器工作流程介紹,輸入網(wǎng)址回車以后瀏覽器向服務(wù)器發(fā)起服務(wù)之前,會(huì)現(xiàn)在瀏覽器緩存中查詢是否有需要的文件?如果有則直接在緩存中獲取文件,避免向服務(wù)器請(qǐng)求和下載文件,所以節(jié)省了一部分時(shí)間。
2.2、瀏覽器緩存優(yōu)點(diǎn)
1、減少網(wǎng)絡(luò)帶寬消耗
對(duì)于網(wǎng)站運(yùn)營者或者訪問網(wǎng)頁的用戶,帶寬就代表著 money ,過多的消耗帶寬,我們服務(wù)器配置就得升級(jí),使用瀏覽器緩存之后,就會(huì)減少網(wǎng)絡(luò)流量,降低運(yùn)營成本。
2、降低服務(wù)器壓力
使用瀏覽器緩存之后,除第一次訪問需要向服務(wù)器請(qǐng)求網(wǎng)站全部資源,后續(xù)訪問可以重復(fù)使用瀏覽器本地緩存,減少對(duì)服務(wù)器的請(qǐng)求,間接降低服務(wù)器的壓力,同時(shí),搜索引擎的爬蟲也會(huì)根據(jù)緩存過期機(jī)制降低抓取的頻率,也可以降低服務(wù)器壓力。
3、減少網(wǎng)絡(luò)延遲,加快網(wǎng)頁加載
瀏覽器緩存 web資源后,減少網(wǎng)絡(luò)請(qǐng)求,可以更快速地獲取到服務(wù)器返回?cái)?shù)據(jù),同時(shí)使用瀏覽器緩存內(nèi)的文件比服務(wù)器獲取快很多,所以網(wǎng)頁加載速度明顯快很多。
對(duì)于瀏覽器端的緩存來講,這些規(guī)則是在 http 協(xié)議和 meta 標(biāo)簽中定義的。分別從兩個(gè)維度:新鮮度和校驗(yàn)值,規(guī)定瀏覽器是否可以直接使用緩存中的副本,還是直接從服務(wù)器獲取最新資源。
3.1、新鮮度(過期):瀏覽器緩存的有效期,緩存必須滿足以下兩個(gè)條件,瀏覽器才會(huì)認(rèn)為是最新的,可以直接使用。
3.2、校驗(yàn)值(驗(yàn)證):服務(wù)器返回資源的時(shí)候,會(huì)在響應(yīng)頭信息中帶上資源實(shí)體標(biāo)簽 Entity Tag,可以用來作為瀏覽器再次請(qǐng)求過程的校驗(yàn)標(biāo)識(shí),如果發(fā)現(xiàn)校驗(yàn)標(biāo)識(shí)不匹配,說明資源已經(jīng)被修改過或過期,瀏覽器需要重新請(qǐng)求資源。
緩存規(guī)則可以設(shè)置在html的meta標(biāo)簽,也可以設(shè)置在http協(xié)議頭內(nèi)。
4.1、前端 html 中 meta 標(biāo)簽
在 html 頁面中加入緩存設(shè)置,代碼如下:
<meta http-equiv="Pragma" content="no-cache" />
<!-- Pragma是http1.0版本中給客戶端設(shè)定緩存方式之一 -->
上邊代碼,禁止瀏覽器緩存,瀏覽器每次訪問網(wǎng)頁都要去服務(wù)器請(qǐng)求。事實(shí)這種禁用緩存形式作用有限:
4.2、HTTP協(xié)議頭
http請(qǐng)求和響應(yīng)頭中,與緩存相關(guān)的常見類型:
規(guī)則 | 消息報(bào)頭 | 值/示例 | 類型 | 作用 |
新鮮度 | Pragma | no-cache | 響應(yīng) | 告訴瀏覽器忽略資源的緩存副本,每次訪問都需要去服務(wù)器拉取【http1.0中存在的字段,在http1.1已被拋棄,使用Cache-Control替代,但為了做http協(xié)議的向下兼容,很多網(wǎng)站依舊會(huì)帶上這個(gè)字段】 |
Expires | Mon, 15 Aug 2016 03:56:47 GMT | 響應(yīng) | 啟用緩存和定義緩存時(shí)間。告訴瀏覽器資源緩存過期時(shí)間,如果還沒過該時(shí)間點(diǎn)則不發(fā)請(qǐng)求【http1.0中存在的字段,該字段所定義的緩存時(shí)間是相對(duì)服務(wù)器上的時(shí)間而言的,如果客戶端上的時(shí)間跟服務(wù)器上的時(shí)間不一致(特別是用戶修改了自己電腦的系統(tǒng)時(shí)間),那緩存時(shí)間可能就沒啥意義了。在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代】 | |
Cache-Control | no-cache | 響應(yīng) | 告訴瀏覽器忽略資源的緩存副本,強(qiáng)制每次請(qǐng)求直接發(fā)送給服務(wù)器,拉取資源,但不是“不緩存” | |
no-store | 響應(yīng) | 強(qiáng)制緩存在任何情況下都不要保留任何副本 | ||
max-age=[秒] | 響應(yīng) | 指明緩存副本的有效時(shí)長,從請(qǐng)求時(shí)間開始到過期時(shí)間之間的秒數(shù) | ||
public | 響應(yīng) | 任何路徑的緩存者(本地緩存、代理服務(wù)器),可以無條件的緩存該資源 | ||
private | 響應(yīng) | 只針對(duì)單個(gè)用戶或者實(shí)體(不同用戶、窗口)緩存資源 | ||
Last-Modified | Mon, 15 Aug 2016 03:56:47 GMT | 響應(yīng) | 告訴瀏覽器這個(gè)資源最后的修改時(shí)間。服務(wù)器將資源傳遞給客戶端時(shí),會(huì)將資源最后更改的時(shí)間以“Last-Modified: GMT”的形式加在實(shí)體首部上一起返回給客戶端【只能精確到秒級(jí),如果某些文件在1秒鐘以內(nèi),被修改多次的話,它將不能準(zhǔn)確標(biāo)注文件的修改時(shí)間】 | |
If-Modified-Since | Mon, 15 Aug 2016 03:56:47 GMT | 請(qǐng)求 | 其值為上次響應(yīng)頭的Last-Modified值,再次向web服務(wù)器請(qǐng)求時(shí)帶上頭If-Modified-Since。web服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有頭If-Modified-Since則與被請(qǐng)求資源的最后修改時(shí)間進(jìn)行比對(duì)。若最后修改時(shí)間較新,說明資源又被改動(dòng)過,則響應(yīng)整片資源內(nèi)容(寫在響應(yīng)消息包體內(nèi)),包括更新Last-Modified的值,HTTP 200;若最后修改時(shí)間較舊,說明資源無新修改,則響應(yīng)HTTP 304(無需請(qǐng)求,節(jié)省瀏覽),告知瀏覽器繼續(xù)使用所保存的cache | |
校驗(yàn)值 | ETag | "fd56273325a2114818df4f29a628226d" | 響應(yīng) | 告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(shí)符(生成規(guī)則由服務(wù)器決定) |
If-None-Match | "fd56273325a2114818df4f29a628226d" | 請(qǐng)求 | 當(dāng)資源過期時(shí)(使用Cache-Control標(biāo)識(shí)的max-age),發(fā)現(xiàn)資源具有Etage聲明,則再次向web服務(wù)器請(qǐng)求時(shí)帶上頭If-None-Match(Etag的值)。web服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有頭If-None-Match則與被請(qǐng)求資源的相應(yīng)校驗(yàn)串進(jìn)行比對(duì),決定返回200或304 |
各種類型之間的關(guān)系和區(qū)別:
并不是所有的請(qǐng)求都能被緩存,無法被緩存的有:
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。