Node实现浏览器缓存

原理

当浏览器第一次向服务端发送请求时,服务端会返回一个带有Last-Modified: Sat, 02 Dec 2017 04:03:14 GMT字段的响应头,该字段表明所请求的文件最新修改时间;当浏览器下一次向服务端发送请求时,请求头会带上 If-Modified-Since: Sat, 02 Dec 2017 04:03:14 GMT字段,该字段的值是上一次服务器 Last-Modified 返回的值,服务器接收到请求后会根据 If-Modified-Since 值进行判断,如果该值小于服务器文件的值则返回新的文件,否则就告诉浏览器使用缓存文件。
举个例子,当浏览器第一次请求时
Node实现浏览器缓存_第1张图片
Node实现浏览器缓存_第2张图片
当浏览器第二次发送请求时
Node实现浏览器缓存_第3张图片

Node实现浏览器缓存_第4张图片

思路

  • 服务器对浏览器请求的请求头if-modified-since进行判断,若不存在,则发送文件以及请求头Last-Modified,说明该文件的修改时间
  • 若存在请求头if-modified-since,将请求头if-modified-since的值与文件修改时间进行比较
  • 如果请求头if-modified-since的值小于文件修改时间,则发送文件以及请求头Last-Modified,说明该文件的修改时间
  • 如果请求头if-modified-since的值等于或大于文件修改时间,则返回304状态码,告知浏览器读取缓存文件

实例

没有实现缓存时:
Node实现浏览器缓存_第5张图片

此时每次请求服务器都会重新发送文件(观察状态码)

实现缓存之后:
Node实现浏览器缓存_第6张图片

const http=require('http');
const fs=require('fs');
const url=require('url');

http.createServer( (req, res) => {
  let {pathname} = url.parse(req.url);

  // 获取文件日期
  fs.stat(`.${pathname}`, (err, stat) => {
    if(err) {
      res.writeHeader(404);
      res.write('Not Found');
      res.end();
    }else {
      if (req.headers['if-modified-since']) {
        // 浏览器 if-modified-since 字段值
        let oDate = new Date(req.headers['if-modified-since']);
        let time_client = Math.floor(oDate.getTime() / 1000);
        
        // 服务端文件最新修改时间
        let time_server = Math.floor(stat.mtime.getTime() / 1000);

        if (time_client < time_server) {
          // 浏览器缓存文件的修改时间小于服务端文件修改时间,发送文件
          sendFileToClient();
        }else {
          // 浏览器缓存文件的修改时间等于或大于服务器文件的修改时间
          // 发送 304 状态码,告知浏览器从缓存中读取数据
          res.writeHeader(304);
          res.write('Not Modified');
          res.end();
        }

      }else {
        // 浏览器是第一次请求该文件,不存在 if-modified-since 字段
        // 从服务器端读取文件
        sendFileToClient();
      }

      function sendFileToClient() {
        let rs = fs.createReadStream(`.${pathname}`);

        // 设置请求头 Last-Modified 字段,值为该文件最新修改时间
        res.setHeader('Last-Modified', stat.mtime.toGMTString());

        // 输出
        rs.pipe(res);

        rs.on('error', err => {
          res.writeHeader(404);
          res.write('Not Found');
          res.end();
        });
      }
    }
  })
}).listen(1337);

你可能感兴趣的:(node)