一直很想學(xué)習(xí)緩存這一塊兒的東西,畢竟前端性能優(yōu)化緩存在其中占了很大一部分作用。緩存分為兩種:強(qiáng)制緩存和協(xié)商緩存。看過很多文章講它們之間的區(qū)別,但是沒有實(shí)戰(zhàn)過只知道其意義卻不知道怎樣去設(shè)置,沒有實(shí)戰(zhàn)過也導(dǎo)致記憶總是很模糊,實(shí)踐才是最好的老師!記錄一下我使用nginx服務(wù)器學(xué)習(xí)緩存的過程。
初探
首先我在 nginx 的根目錄下新建了一個(gè) index.html
文件以及 index.js
文件。此時(shí) nginx
的配置文件是長(zhǎng)這個(gè)樣子的:
server {
listen 8080;
server_name localhost;
location / {
root /Volumes/myFile/nginx_root;
index index.html index.htm;
}
}
然后我們?yōu)g覽器訪問 localhost:8080。打開控制臺(tái),發(fā)現(xiàn)里面有兩條請(qǐng)求:

可以看到第一次訪問,兩條請(qǐng)求的狀態(tài)碼都是 200。我們點(diǎn)開其中一條請(qǐng)求看看響應(yīng)頭信息:

可以看到,響應(yīng)頭中給我們攜帶了 Etag
以及 Last-Modified
信息。這就是協(xié)商緩存所使用的字段嘛。看來 nginx 已經(jīng)默認(rèn)給我們使用了緩存。那我們?cè)诓恍薷?html文件以及js文件的基礎(chǔ)上再次去刷新頁(yè)面驗(yàn)證一下,命中協(xié)商緩存的話,狀態(tài)碼應(yīng)該給我們返回 304 Not Modified
。我刷新了幾次去觀察http請(qǐng)求的狀態(tài)碼。html文件每次都是返回的 304。但是 js 文件在最初是 304 后面卻變成了 200 OK (from memory cache)
。也就是說每一次html文件都是命中了協(xié)商緩存,而js文件都是命中了強(qiáng)緩存(強(qiáng)緩存的優(yōu)先級(jí)是高于協(xié)商緩存的)。為什么會(huì)出現(xiàn)這樣的情況呢,我百度一下:
為什么有的緩存是 200 OK (from cache),有的緩存是 304 Not Modified 呢?很簡(jiǎn)單,看是否移除了 Entity Tag。移除了,就總是 200 OK (from cache)。沒有移除,就兩者會(huì)交替出現(xiàn)。
那么,兩者觸發(fā)的時(shí)機(jī)有什么區(qū)別呢?200 OK (from cache) 是直接點(diǎn)擊鏈接訪問,輸入網(wǎng)址按回車訪問也能觸發(fā);而 304 Not Modified 是刷新頁(yè)面時(shí)觸發(fā),或是設(shè)置了強(qiáng)緩存、但 Entity Tags 沒有移除時(shí)觸發(fā)。
對(duì)照我的例子,我是這樣理解的: index.html
文件刷新頁(yè)面命中協(xié)商緩存返回了 304,而 js 文件是在 index.html 文件中鏈接引入的,所以命中強(qiáng)緩存 200 OK (from cache) 。為了驗(yàn)證我的想法,我用在地址欄直接訪問了 index.js
文件。地址欄鍵入:localhost:8080/index.js,此時(shí)的確是返回了 304 給我了,在來看一下此時(shí)的請(qǐng)求頭:

可以看到此時(shí) Cache-Control
給的是max-age=0;然后也攜帶上了協(xié)商緩存的相關(guān)參數(shù)。看來在瀏覽器是刷新操作的時(shí)候就會(huì)攜帶上 Cache-Control:max-age=0
以此來避免命中強(qiáng)緩存。
nginx禁用強(qiáng)緩存
在試試 nginx 禁用強(qiáng)緩存之后會(huì)發(fā)生什么效果。修改 nginx 配置文件:
server {
listen 8080;
server_name localhost;
location / {
root /Volumes/myFile/nginx_root;
index index.html index.htm;
add_header Cache-Control no-cache;
# 為 public可以被任何對(duì)象緩存,private只能針對(duì)個(gè)人用戶,而不能被代理服務(wù)器緩存
add_header Cache-Control private;
}
}
修改完 nginx 配置文件之后我們重啟一下 nginx 服務(wù)器。此時(shí)在訪問 localhost:8080

可以看到,此時(shí) html 文件和 js文件都是 304 都是命中協(xié)商緩存了。
Cache-Control: no-store
禁止一切緩存(這個(gè)才是響應(yīng)不被緩存的意思)。緩存通常會(huì)像非緩存代理服務(wù)器一樣,向客戶端轉(zhuǎn)發(fā)一條 no-store 響應(yīng),然后刪除對(duì)象。
Cache-Control:no-cache
強(qiáng)制客戶端直接向服務(wù)器發(fā)送請(qǐng)求,也就是說每次請(qǐng)求都必須向服務(wù)器發(fā)送。服務(wù)器接收到請(qǐng)求,然后判斷資源是否變更,是則返回新內(nèi)容,否則返回304,未變更。這個(gè)很容易讓人產(chǎn)生誤解,使人誤以為是響應(yīng)不被緩存。實(shí)際上Cache-Control: no-cache是會(huì)被緩存的,只不過每次在向客戶端(瀏覽器)提供響應(yīng)數(shù)據(jù)時(shí),緩存都要向服務(wù)器評(píng)估緩存響應(yīng)的有效性。
其實(shí)將 Cache-Control 設(shè)置為 no-store 才是真正的不被緩存的意思,那在修改一下 nginx 文件將 Cache-Control 設(shè)置為 no-store 看看會(huì)發(fā)生什么。此時(shí)再次刷新瀏覽器。

可以看到,修改完 nginx 的配置文件之后,除了第一次是304(這次訪問瀏覽器才剛剛接收到 no-store的信息,請(qǐng)求頭上還是攜帶了緩存相關(guān)信息) 外,剩下的幾次刷新頁(yè)面都是返回 200了。既沒有命中強(qiáng)緩存、也沒有命中協(xié)商緩存。在看一下 index.js
文件的 http 頭信息。

這里的圖我沒有截完整,其實(shí)響應(yīng)頭中還包含了 Cache-Control: no-store 。可以看到,在 Cache-Control: no-store 的加持下,即使在響應(yīng)頭中服務(wù)請(qǐng)返回了協(xié)商緩存的參數(shù),但是在瀏覽器在請(qǐng)求資源的時(shí)候,并沒有帶上緩存相關(guān)的參數(shù)了,所以,現(xiàn)在沒有緩存了,既不會(huì)命中強(qiáng)緩存,也不會(huì)命中協(xié)商緩存,每一次http請(qǐng)求的資源都是從服務(wù)器上返回的。
結(jié)語(yǔ)
這次的探索到現(xiàn)在就結(jié)束了,其實(shí)就是我一次學(xué)習(xí)的記錄吧。實(shí)踐了一次之后確實(shí)對(duì)緩存有了更清晰的理解和認(rèn)知,果真實(shí)踐出真知。后續(xù)打算還會(huì)記錄一篇在現(xiàn)在前端使用 React.js 或者 Vue.js 等框架打包之后前端資源如何利用 nginx 做部署還有配置相關(guān)緩存的文章,到時(shí)候在看有沒有記錄下來的意義把。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。