http缓存
web缓存 包括 浏览器缓存 和 http缓存,浏览器缓存主要是 本地存储、cookie等数据存储。而http缓存主要是缓存静态文档。
http缓存,是由服务器在响应头上添加字段设置的。web服务器一般默认开启http缓存的,用nodejs 创建的web服务器默认没有开启,需要手动配置。
参考:https://juejin.cn/post/7127194919235485733?share_token=87297877-3258-4769-a434-86cbf5529321
强缓存
-
Expires:这个是绝对时间,和 用户电脑的时间做比较。【标准中已经废弃这个字段,浏览器中还是有效的】
-
Cache-control:可以控制强缓存,也可以控制协商缓存。
- max-age:相对的缓存时间,单位是s
- no-cache:表示为强制使用协商缓存,不去判断强缓存是否过期。
- no-store:禁止使用任何缓存策略。
-
强缓存显示的状态码是,200。
const http = require('http')
const fs = require("fs")
const url = require('url')
http.createServer((req, res) => {
console.log(req.method, req.url);
const { pathname } = url.parse(req.url)
if(pathname === '/'){
const data = fs.readFileSync("./index.html")
res.end(data)
} else if(pathname === '/img/01.jpeg'){
const data = fs.readFileSync("./img/01.jpeg")
res.writeHead(200, {
Expires: new Date('2022-11-14 10:20:00').toUTCString()
})
res.end(data)
} else if(pathname === '/img/02.jpeg'){
const data = fs.readFileSync("./img/02.jpeg")
res.writeHead(200, {
"Cache-control": "max-age=10" // 单位s
})
res.end(data)
} else {
res.statusCode = 404
res.end()
}
}).listen(3000, () => {
console.log("http://localhost:3000");
})
协商缓存 【相对会绕一点,详细可以看文档】
原理:协商缓存命中时,服务响应 304就是使用缓存文档;如果是200,就是没有使用缓存文档,响应体同时把最新的文档给浏览器了。
基于last-modified的协商缓存实现方式是:
-
last-modified:
设置了 last-modified协商缓存后,第二次请求时,请求头上会自动添加上 if-modified-since 字段。web服务器一般通过 比较这两个值是不是一直,决定是不是返回304。
基于ETag的协商缓存:
说明:last-modified 缓存存在一些缺陷,修改文件名再改回来时,文件名称和内容都没有改变,只是修改时间变了。服务器会判定 缓存失效,重新获取文档。
ETag就是将原先协商缓存的比较时间戳的形式修改成了比较文件指纹。
-
etag:
设置了etag协商缓存后,第二次请求时,请求头上会自动添加上 if-none-match 字段。web服务器一般通过 比较这两个值是不是一直,决定是不是返回304。
const http = require('http')
const fs = require("fs")
const url = require('url')
const etag = require('etag')
http.createServer((req, res) => {
console.log(req.method, req.url);
const { pathname } = url.parse(req.url)
if(pathname === '/'){
const data = fs.readFileSync("./index.html")
res.end(data)
} else if(pathname === '/img/02.jpeg'){
// 协商缓存-【基于last-modified实现】
const { mtime } = fs.statSync('./img/02.jpeg')
const ifModifiedSince = req.headers['if-modified-since']
if(ifModifiedSince === mtime.toUTCString()){
res.statusCode = 304 // 返回304 就是告诉浏览器,使用缓存文档。
res.end()
return
}
const data = fs.readFileSync("./img/02.jpeg")
res.setHeader("Cache-control", "no-cache")
res.setHeader("last-modified", mtime.toUTCString())
res.end(data)
} else if(pathname === '/img/03.jpeg'){
// 协商缓存-【基于 etag 实现】
const data = fs.readFileSync("./img/03.jpeg")
const etagContent = etag(data)
const ifNoneMatch = req.headers['if-none-match']
if(ifNoneMatch === etagContent){
res.statusCode = 304 // 返回304 就是告诉浏览器,使用缓存文档。
res.end()
return
}
res.setHeader("etag", etagContent)
res.setHeader("Cache-control", "no-cache")
res.end(data)
} else {
res.statusCode = 404
res.end()
}
}).listen(3000, () => {
console.log("http://localhost:3000");
})
总结:
强缓存和协商缓存的最大区别 在于 判断缓存命中时,浏览器是否需要向服务器端进行询问以协商缓存的相关信息。
当命中 强缓存 时,直接从缓存中取出文档。
当命中协商缓存时,还要去服务器确认下,是不是从缓存中取出。

浙公网安备 33010602011771号