Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

缓存 #95

Open
AlexZ33 opened this issue Jun 22, 2020 · 3 comments
Open

缓存 #95

AlexZ33 opened this issue Jun 22, 2020 · 3 comments

Comments

@AlexZ33
Copy link
Owner

AlexZ33 commented Jun 22, 2020

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
Copy link
Owner Author

AlexZ33 commented Mar 22, 2021

image

@AlexZ33
Copy link
Owner Author

AlexZ33 commented Mar 22, 2021

image

@AlexZ33
Copy link
Owner Author

AlexZ33 commented Mar 22, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant