学习node.js 十四,http强缓存与协商缓存

http缓存

HTTP缓存主要分为两大类:强缓存和协商缓存。这两种缓存都通过 HTTP 响应头来控制,目的是提高网站性能。

强缓存介绍

强缓存之后则不需要向服务器发送请求,而是从浏览器缓存读取分为(内存缓存)| (硬盘缓存

  1. memory cache(内存缓存)
    内存缓存存储在浏览器内存当中,一般刷新网页的时候会发现很多内存缓存
  2. disk cache(硬盘缓存)
    硬盘缓存是存储在计算机硬盘中,空间大,但是读取效率比内存缓存慢
强缓存案例(Expires)

Expires: 该字段指定响应的到期时间,即资源不再被视为有效的日期和时间。它是一个 HTTP 1.0 的头部字段,但仍然被一些客户端和服务器使用

Expires 的判断机制是:当客户端请求资源时,会获取本地时间戳,然后拿本地时间戳与 Expires 设置的时间做对比,如果对比成功,走强缓存,对比失败,则对服务器发起请求。

代码案例:

node

import express from 'express'
import cors from 'cors'

const app = express()
app.use(cors())
app.use(express.json())

// 利用expires设置强缓存
app.get('/api', (req, res) => {
    res.setHeader("Expires",new Date("2024-9-6 9:11:00").toUTCString())
    res.send({
        code: 200,
        data: "hello world"
    })
})


app.listen(3000,() => console.log('Server is running on port 3000'))

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<button id="btn">download</button>

<script>
    const btn = document.getElementById('btn')
    btn.onclick = () => {
        fetch("http://localhost:3000/api",{
            method: "GET",
        }).then(res => res.json()).then(res => { console.log(res)})
    }
</script>
</body>
</html>

没过期之前使用缓存的值,过期之后从服务器读取

强缓存案例(Cache-Control)

Cache-Control 的值如下:

  • max-age:浏览器资源缓存的时长(秒)。
  • no-cache:不走强缓存,走协商缓存
  • no-store:禁止任何缓存策略。
  • public:资源即可以被浏览器缓存也可以被代理服务器缓存(CDN)。
  • private:资源只能被客户端缓存

如果 max-age 和 Expires 同时出现 max-age 优先级高

代码案例

// 利用cache-controller设置强缓存
app.get('/api', (req, res) => {
    res.setHeader("cache-control", "max-age=60")
    res.send({
        code: 200,
        data: "hello world"
    })
})
const btn = document.getElementById('btn')
    btn.onclick = () => {
        fetch("http://localhost:3000/api",{
            method: "GET",
        }).then(res => res.json()).then(res => { console.log(res)})
    }

协商缓存介绍

当涉及到缓存机制时,强缓存优先于协商缓存。当资源的强缓存生效时,客户端可以直接从本地缓存中获取资源,而无需与服务器进行通信。强缓存的判断是通过缓存头部字段来完成的,例如设置了合适的Cache-ControlExpires字段。

如果强缓存未命中(例如max-age过期),或者服务器响应中设置了Cache-Control: no-cache,则客户端会发起协商缓存的请求。在协商缓存中,客户端会发送带有缓存数据标识的请求头部字段,以向服务器验证资源的有效性。

服务器会根据客户端发送的协商缓存字段(如If-Modified-Since和If-None-Match)来判断资源是否发生变化。如果资源未发生修改,服务器会返回状态码 304(Not Modified),通知客户端可以使用缓存的版本。如果资源已经发生变化,服务器将返回最新的资源,状态码为 200。

协商缓存(Last-Modified)

Last-Modified 和 If-Modified-Since:服务器通过 Last-Modified 响应头告知客户端资源的最后修改时间。客户端在后续请求中通过 If-Modified-Since 请求头携带该时间,服务器判断资源是否有更新。如果没有更新,返回 304 状态码。
首先会获取到文件的最后修改时间,发给客户端,Last-Modified会被存到 If-Modified-Since上面,下次请求时会被携带,如果一致,则表示文件未修改,可以走协商缓存

app.get('/api', (req, res) => {
    res.setHeader("cache-control", "no-cache, max-age=2592000")
    res.setHeader("last-modified", getLastModifiedTime())
    const ifLastModified = req.headers['if-modified-since']
    console.log(ifLastModified === getLastModifiedTime())
    if (ifLastModified === getLastModifiedTime()) {
        console.log(304)
        res.statusCode = 304
        res.end()
        return
    }else {
        res.send('Hello World!')
    }
})
协商缓存(ETag)

ETag 和 If-None-Match:服务器通过 ETag 响应头给资源生成一个唯一标识符。客户端在后续请求中通过 If-None-Match 请求头携带该标识符,服务器根据标识符判断资源是否有更新。如果没有更新,返回 304 状态码。

ETag 优先级比 Last-Modified 高

// 获取文件的最后修改时间
function getLastModifiedTime() {
    return crypto.createHash('sha256').update(fs.readFileSync('index.js')).digest('hex')
}
// 利用last-modified和etag实现缓存
app.get('/api', (req, res) => {
    res.setHeader("cache-control", "no-cache, max-age=2592000")
    const ifLastModified = req.headers['if-none-match']
    const etag = getLastModifiedTime()
    if (ifLastModified === etag) {
        console.log(304)
        res.statusCode = 304
        res.end()
        return
    }
    res.setHeader("Etag", etag)
    res.send({
        data: 'hello world'
    })
})
  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值