目錄
- 緩存驗(yàn)證的參數(shù)
- 服務(wù)端如何驗(yàn)證緩存?
0. 概述
上一章介紹了使用Cache-Control中max-age的使用,但是有時(shí)候我們希望在客戶(hù)端使用本地緩存前,先詢(xún)問(wèn)下服務(wù)端能否使用這個(gè)緩存,這個(gè)操作被稱(chēng)為緩存驗(yàn)證。
下圖為驗(yàn)證的流程。

1. 緩存驗(yàn)證的參數(shù)
-
修改服務(wù)端代碼
- 緩存驗(yàn)證在服務(wù)端的響應(yīng)頭中使用
Etag或Last-Modified參數(shù),個(gè)人認(rèn)為這兩個(gè)參數(shù)的區(qū)別在于語(yǔ)意,Last-Modified通常根據(jù)更新時(shí)間來(lái)判斷,而Etag可以自定義任何的值??蛻?hù)端的請(qǐng)求頭中的參數(shù)見(jiàn)下圖。 - 更改
max-age,讓本地緩存短時(shí)間內(nèi)不會(huì)過(guò)期。 - 增加
no-cache(用逗號(hào)分隔),no-cache參數(shù)的作用:允許瀏覽器存儲(chǔ)緩存,但是必須訪(fǎng)問(wèn)服務(wù)端去驗(yàn)證,由服務(wù)端決定能否使用緩存。 - 在這里我們隨意為
Etag和Last-Modified賦值。
const http = require('http')
const fs = require('fs')
const port = 9000
http.createServer(function (request, response) {
console.log('request from ', request.url)
if (request.url === '/') {
// 讀取html發(fā)送
const html = fs.readFileSync('index.html', 'utf-8')
response.writeHead(200, {
'Content-Type': 'text/html'
})
response.end(html)
}
else if (request.url === '/script.js') {
// 返回響應(yīng)
response.writeHead(status, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=1000000, no-cache',
'Etag': 'dyq666',
'Last-Modified': '111',
})
response.end(“console.log('script')”)
}
}).listen(port)
console.log("serve is listen ", port)
-
觀察請(qǐng)求頭與響應(yīng)頭
緩存相關(guān)的測(cè)試,如果不成功,可能是沒(méi)有清楚瀏覽器緩存,導(dǎo)致之前的頁(yè)面緩存在瀏覽器中。
-
第一次發(fā)送請(qǐng)求,響應(yīng)頭中會(huì)返回參數(shù)。
-
第二次發(fā)送請(qǐng)求,瀏覽器會(huì)自動(dòng)將第一次從響應(yīng)頭中得到的值,通過(guò)瀏覽器規(guī)定的參數(shù)名發(fā)送給服務(wù)端。
image.png
2. 服務(wù)端如何驗(yàn)證緩存?
-
修改服務(wù)端代碼
- 判斷請(qǐng)求頭中的參數(shù)的值是否與之前設(shè)置的值相同(代碼中判斷的是
if-none-match,也就是Etag對(duì)應(yīng)的參數(shù))。 - 如果相同,證明客戶(hù)端可以使用緩存,則返回
304和空的內(nèi)容,瀏覽器會(huì)根據(jù)狀態(tài)碼304去使用緩存。 - 如果不相同,證明客戶(hù)端無(wú)法使用緩存,則返回一個(gè)
200和對(duì)應(yīng)的內(nèi)容,并將當(dāng)前最新的Etag返回。
/**
* 1. 驗(yàn)證緩存是否有效
*/
const http = require('http')
const port = 9000
http.createServer(function (request, response) {
const url = request.url
switch(url) {
case '/': {
response.writeHead(200, {
'Content-Type': 'text/html'
})
response.end('<script src="/script.js"></script>')
}
case '/script.js': {
if (request.headers['if-none-match'] === 'dyq666') {
status = 304
body = ''
} else {
status = 200
body = 'console.log("It is script")'
}
response.writeHead(status, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=100000, no-cache',
'Etag': 'dyq666',
'Last-Modified': '111'
})
response.end(body)
}
}
}).listen(port)
console.log("serve is listen ", port)
-
觀察響應(yīng)碼
- 第一次響應(yīng)中的狀態(tài)碼是
200
- 第二次響應(yīng)中的狀態(tài)碼是
304



