概述
当我们给Catch-Control 设置了 no-catch 后,每次浏览器对这个资源的请求时,都会到服务器端进行资源验证,验证完之后,如果确定这个资源可以使用缓存,浏览器才会读取本地的缓存。
缓存验证流程
方式
验证资源是否需要更新有两种方式: Last-Modified 与 Etag
Last-Modified
上次修改时间。主要配合If-Modified-Since 或者 If-Unmodified-Since 这两个Header 使用。
通过对比请求首部字段If-Modified-Since和实体首部字段 Last-Modified,来判断是否使用缓存。
如果我们请求的一个资源,它返回的Header 中有Last-Modified 并指定了一个时间。那么下次浏览器再发送这个请求的时候就会带上这个时间,并把它放在 If-Modified-Since中;服务器就可以根据If-Modified-Since值对比资源上次修改的时间,如果两个时间一致,说明请求的资源都没有过更新,那么就可以使用缓存
Etag
是一个更为严格的验证,通过数据签名的方式验证。主要配合 If-Match 或者 If-None-Match 使用。
它根据数据内容产生一个唯一的编码(数据不同,编码结果不同)。最典型的做法,是我们对数据内容做一个哈希计算。
当服务端加上Last-Modified
,Etag
,浏览器下次请求就会带上If-Modified-Since
和If-None-Match
,来进行缓存验证。
使用缓存实例
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script src="/script.js"></script>
</html>
server.js
const http = require('http')
const fs = require('fs')
http.createServer(function (request, response) {
console.log('request come', request.url)
if (request.url === '/') {
const html = fs.readFileSync('test.html', 'utf8')
response.writeHead(200, {
'Content-Type': 'text/html'
})
response.end(html)
}
if (request.url === '/script.js') {
const etag = request.headers['if-none-match']
if (etag === '777') {
response.writeHead(304, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=2000000, no-cache',
'Last-Modified': '123',
'Etag': '777'
})
response.end()
} else {
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=2000000, no-cache',
'Last-Modified': '123',
'Etag': '777'
})
response.end('console.log("script loaded twice")')
}
}
}).listen(8888)
console.log('server listening on 8888')
使用node server.js
启动,在http://localhost:8888/
上查看server.js的网络请求。
可以发现,状态码第一次是200,第二次及以后缓存范围期限内,都是304