AlexZ33 / lessions

自己练习的各种demo和课程
12 stars 2 forks source link

缓存 #95

Open AlexZ33 opened 4 years ago

AlexZ33 commented 4 years ago

https://www.cnblogs.com/floor/p/9867194.html

公众号原文阅读:HTTP缓存机制 浏览器缓存思维笔记 (2)

缓存策略

协商缓存

顾名思义,需要客户端跟服务器协商共同解决缓存问题。

协商缓存可使用的头组合有 Last-Modified/if-Modify-Since 和 ETag/if-None-Match

需要服务端手动处理判断请求头字段,以 node 部分代码为例: 1、Last-Modified/if-Modify-Since

  // 获取 if-modified-since 这个请求头
  const ifModifiedSince = req.headers['if-modified-since'];
  // 获取最后修改的时间
  const lastModified = stat.ctime.toGMTString();
  // 判断两者是否相等,如果相等返回304读取浏览器缓存。否则的话,重新发请求
  if (ifModifiedSince === lastModified) {
    res.writeHead(304);
    res.end();
  } else {
    res.setHeader('Content-Type', mime.getType(filepath));
    res.setHeader('Last-Modified', stat.ctime.toGMTString());
    // fs.createReadStream(filepath).pipe(res);
  }
  1. ETag/if-None-Match
//Etag 实体内容,他是根据文件内容,算出一个唯一的值。 
let md5 = crypto.createHash('md5') 
let rs = fs.createReadStream(abs) 
let arr = []; 
// 你要先写入响应头再写入响应体 
rs.on('data', function(chunk) { 
    md5.update(chunk); arr.push(chunk) 
}) 

rs.on('end', function() { 
    let etag = md5.digest('base64'); 
    if(req.headers['if-none-match'] === etag) { 
        console.log(req.headers['if-none-match']) 
        res.statusCode = 304; 
        res.end() 
        return 
     } 
     res.setHeader('Etag', etag) 
     // If-None-Match 和 Etag 是一对, If-None-Match是浏览器的, Etag是服务端的 
     res.end(Buffer.concat(arr)) 
})

image

强制缓存

浏览器在加载资源的时候,会先根据本地缓存资源的header中的信息(Expires 和 Cache-Control)来判断是否需要强制缓存。如果命中的话,则会直接使用缓存中的资源。否则的话,会继续向服务器发送请求。

关联的头字段有 Expires 和 Cache-Control

1、Expires

表示缓存到期时间,是 当前时间+缓存时间,浏览器在未过期之前不需要再次请求。 服务端代码以 nodejs 为例:

let { pathname } = url.parse(req.url, true); 
let abs = path.join(__dirname, pathname); 

res.setHeader('Expires', new Date(Date.now() + 20000).toGMTString()); 

fs.stat(path.join(__dirname, pathname), (err, stat) => { 
    if(err) { 
        res.statusCode = 404; 
        res.end('not found') 
        return 
        } 
    if(stat.isFile()) { 
        fs.createReadStream(abs).pipe(res) 
    } 
})

2、Cache-Control 键值列表 image

服务端代码 以 node 为例:

res.setHeader('Cache-Control', 'max-age=20')
res.setHeader('Cache-Control', 'no-store')
res.setHeader('Cache-Control', 'no-cache')

多个值用逗号分隔

res.setHeader('Cache-Control', 'public, max-age=1024')

注意:

禁止缓存应该使用 no-store 而不是 no-cache 指定 no-cache 或 max-age=0 表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。这样既可以保证内容的有效性,又可以保证能获取到最新的内容。

image

AlexZ33 commented 3 years ago

image

AlexZ33 commented 3 years ago

image

AlexZ33 commented 3 years ago

参考

深入理解浏览器的缓存机制 https://www.cnblogs.com/suihang/p/12855345.html