# 缓存验证 Last-Modified 和 Etag 的使用

如果我们设置了 Cache-Control 设置了 no-cache 之后;那么每次浏览器对已经设置了 Cache-Control 的资源的请求的时候,都要去服务器端进行一个资源的验证,验证完之后,如果确定这个资源可以使用缓存,他才会读取本地的缓存。

# 资源验证

从浏览器发送请求到查找缓存的过程:

在这里插入图片描述

# 验证头

  • Last-Modified

上次修改时间,配合 If-Modified-Since 或者 If-Unmodified-Since 使用;也就是说如果请求一个资源,这个资源返回的头中包含 Last-Modified 的设置;在下次浏览器发送请求的时候就会带上 Last-Modified 设置以及 If-Modified-Since 或者 If-Unmodified-Since 到服务器,服务器通过读取这两个值;进行对比文件上次修改的时间,如果发现两个时间一样,代表资源没有修改过,服务器就可以告诉浏览器可以使用本地缓存。

  • Etag

通过数据签名进行验证数据。就是对资源的内容进行计算,生成一个唯一的标识。配合 If-Match 或者 If-Non-Match 使用;对比资源的签名判断是否使用缓存。

# node 实践

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/script.js') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/javascript',
      'cache-Control': 'max-age=20000, no-cache',
      'Last-Modified': '123',
      'Etag': '888'
    })
    res.end('console.log("loaded")')
  }
}).listen(8888)

可以看到,浏览器再次发送请求,Request Headers 会携带信息:也是服务端返回的数据,浏览器会携带上这些缓存头到服务器验证是否使用缓存。

If-Modified-Since: 123
If-None-Match: 888

在服务器端可以通过缓存头进行判断是否要缓存:

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/script.js') {
    const etag = req.headers['if-none-match']
    if (etag === '888') {
      res.writeHead(304, {
        'Content-Type': 'text/javascript',
        'cache-Control': 'max-age=20000, no-cache',
        'Last-Modified': '123',
        'Etag': '888'
      })
      // 这里的返回结果不会再浏览器中返回,是直接使用浏览器中的缓存
      res.end('')
    } else {
      res.writeHead(200, {
        'Content-Type': 'text/javascript',
        'cache-Control': 'max-age=20000, no-cache',
        'Last-Modified': '123',
        'Etag': '888'
      })
      res.end('console.log("loaded")')
    }
  }
}).listen(8888)

no-store 是没有任何缓存的:会忽略任何跟缓存有关的信息。

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/script.js') {
    const etag = req.headers['if-none-match']
    if (etag === '888') {
      res.writeHead(304, {
        'Content-Type': 'text/javascript',
        'cache-Control': 'max-age=20000, no-store',
        'Last-Modified': '123',
        'Etag': '888'
      })
      // 这里的返回结果不会再浏览器中返回,是直接使用浏览器中的缓存
      res.end('')
    } else {
      res.writeHead(200, {
        'Content-Type': 'text/javascript',
        'cache-Control': 'max-age=20000, no-store',
        'Last-Modified': '123',
        'Etag': '888'
      })
      res.end('console.log("loaded")')
    }
  }
}).listen(8888)

评 论:

更新: 11/21/2020, 7:00:56 PM