浏览器缓存机制

浏览器缓存也就是HTTP缓存,其机制是通过http响应头中的相关字段来判断是否启用缓存。浏览器缓存机制有两种:强制缓存协商缓存

浏览器缓存机制如下:

强制缓存

在http响应头中,与强制缓存有关的字段有:Cache-ControlExpires,其中Cache-Control是http1.1中的内容,Expires是http1.0中的内容

Cache-Control

Cache-Control的值可以是以下字段的组合:

作用
public 资源可以被代理服务器缓存
private 资源仅客户端可以缓存
max-age=n 缓存有效时间为n秒
s-max-age=n 同上,只不过仅适用于代理服务器
no-store 不允许缓存
no-cache 不允许强制缓存,允许协商缓存
max-state=n n秒内,即使缓存资源已过期也使用该缓存
min-fresh=n 能够容忍的最小新鲜度

使用Cache-Control的强制缓存流程如下:

在koa中使用:

ctx.set("Cache-Control", "max-age:10;private")
//十秒后资源过期,且仅允许客户端缓存

Expires

如果一个响应头中同时存在Cache-ControlExpires,则前者的优先级更高,主要用于兼容不支持Cache-Control的浏览器

在koa中使用:

ctx.set("Expires", new Date(Date.now() + 10000).toGMTString())
//十秒后资源过期

协商缓存

Last-Modified

即最后修改时间,由服务器返回给客户端,客户端第二次及以后的请求都会自动加上If-Modified-Since请求头,值为服务器上一次返回的Last-Modified的值,服务端收到后会将该值与所请求文件的最后修改时间作比较,如果相同服务器就会返回304状态码,否则返回最新的资源文件

在koa中使用:

const fs = require('fs')
const path = require('path')
//...
app.use(async (ctx, next) => {
    let filename = path.resolve(__dirname,ctx.filename)
    await new Promise((resolve, reject) => {
        fs.stat(filename,(err, stat) => {
            if(err) reject(404)
            //服务器文件最后修改时间
            let last = stat.ctime.toGMTString()
            //客户端得到的文件最后修改时间
            let since = ctx.header['if-modified-since']
            //若 last === since 则表示文件未修改
            if(last === since)
                reject(304)
            else{
                //文件已修改,返回最新修改时间
                resolve(last)
            }
        })
    }).then(res => {
        ctx.set("Last-Modified", res)
        ctx.body = fs.createReadStream(filename)
    }).catch(err => {
        if(err === 304)
            ctx.status = 304
        else{
            ctx.status = 404
            ctx.body = '404 Not Found'
        }
    })
    await next()
})

ETag

Last-Modified,也是由服务器返回给客户端,并且在客户端第二次及以后的请求中都会自动携带上If-None-Match请求头,值为上一次服务器返回的ETag的值(这个值是一个表示文件版本信息的字符串,仅在文件内容发生变化时才会更新该值,支持自定义生成),服务器收到该值后便会与当前所请求文件的版本信息作比较,如果相同则返回状态码304,否则返回最新文件

参考资料



浏览器  

浏览器 缓存机制

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!