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");
})

总结:

强缓存和协商缓存的最大区别 在于 判断缓存命中时,浏览器是否需要向服务器端进行询问以协商缓存的相关信息。

当命中 强缓存 时,直接从缓存中取出文档。

当命中协商缓存时,还要去服务器确认下,是不是从缓存中取出。

posted @ 2025-08-04 08:31  吴飞ff  阅读(4)  评论(0)    收藏  举报