http缓存

http缓存

http缓存我将从理论和实战中演示一次,加深自己对http的缓存的理解。实战主要通过nodejs搭建服务器去进行设置。
主要包括强制缓存和协商缓存
强制缓存
如果浏览器所请求的资源有效命中,则可以直接从强制缓存中返回请求响应,无须与服务器进行任何通信。
通俗的说就是客户端请求服务器拿到服务资源,服务器告诉浏览器你可以进行强制缓存,客户端缓存起来以后,如果下次再请求这个资源,如果缓存没有过期的话,可以直接使用缓存的内容,不需要再发起请求了。缓存主要存的是不经常改变的静态资源
1.1
以下是通过expires设置的强制缓存的代码,主要是通过时间戳实现的

在这里插入代码片
const http = require("http");
const fs = require("fs");
const url = require("url");
http
  .createServer((req, res) => {
    // res.end("hello");
    // console.log(url.parse(req.url));  返回一个对象
    console.log(req.method, req.url);
    let { pathname } = url.parse(req.url);
    if (pathname == "/") {
      const data = fs.readFileSync("./index.html");
      res.end(data);
    } else if (pathname == "/img/qq.png") {
      const data = fs.readFileSync("./img/qq.png");
      res.writeHead(204, {
        Expires: new Date("2021-5-24 13:30:30").toUTCString(),
      });
      res.end(data);
    }
  })
  .listen(3000, () => {
    console.log("http://localhost:3000");
  });

自己可以在控制台查看会发现,第一次时候图片是发起了请求,刷新页面以后再看控制台会发现图片对应的网络请求并没有发送,发送没发送的依据是可以看下控制台的size对应的如果发了请求会显示kb,M`,没法请求会显示缓存对应的英文字母``
但是如果客户端和服务器端时间不同步,那么对于缓存过期的判断可能无法和预期相符,为了解决这种局限性,从http1.1协议开始新增了cache-control字段来对expires的功能进行完善
**1.2**
以下主要通过Cache-Control:"max-age=秒数"来设定,以下为演示代码

在这里插入代码片
const http = require(“http”);
const fs = require(“fs”);
const url = require(“url”);
http
.createServer((req, res) => {
// res.end(“hello”);
// console.log(url.parse(req.url)); 返回一个对象
console.log(req.method, req.url);
let { pathname } = url.parse(req.url);
if (pathname == “/”) {
const data = fs.readFileSync("./index.html");
res.end(data);
} else if (pathname == “/img/qq.png”) {
const data = fs.readFileSync("./img/qq.png");
res.writeHead(200, {
// Expires: new Date(“2021-5-24 13:30:30”).toUTCString(),
“Cache-Control”: “max-age=5”, //单位时间是秒
});
res.end(data);
}
})
.listen(3000, () => {
console.log(“http://localhost:3000”);
});
``
强制缓存在有效期时间内,再次发送请求,并没有发请求,nodejs对应的回调函数并没有执行。

协商缓存
接着看下Cache-Control对应的其他值
设置为no-store为不缓存
设置为no-cache为强制进行协商缓存,也就是对于每次发起的请求都不会再去判断强制缓存是否过期,而是直接与服务器协商来验证缓存的有效性,若缓存没过期,则使用本地缓存
协商缓存解决了啥?
协商缓存主要解决了在强制缓存下资源不更新的问题。
常见的协商缓存主要是通过设置last-modified进行设置的,代码如下

在这里插入代码片
const http = require("http");
const fs = require("fs");
const url = require("url");
http
  .createServer((req, res) => {
    // res.end("hello");
    // console.log(url.parse(req.url));  返回一个对象
    console.log(req.method, req.url);
    let { pathname } = url.parse(req.url);
    if (pathname == "/") {
      const data = fs.readFileSync("./index.html");
      res.end(data);
    } else if (pathname == "/img/qq.png") {
      const data = fs.readFileSync("./img/qq.png");
      // writeHead和setHead的区别 setHead不需要设置状态码,也不需要把配置放在对象里面
      const { mtime } = fs.statSync("./img/qq.png"); //返回的是状态
      const ifModifiedSince = req.headers["if-modified-since"];
      console.log(ifModifiedSince, mtime.toUTCString());
      if (ifModifiedSince === mtime.toUTCString()) {
        // console.log(111);
        //  缓存生效
        res.statusCode = 304; //状态码设置为304,然后浏览器收到是304以后会直接读取缓存
        res.end();
        return;
      }
      res.setHeader("last-modified", mtime.toUTCString());
      res.setHeader("Cache-Control", "no-cache");
      //   console.log(fs.statSync("./img/qq.png"));
      res.end(data);
    }
  })
  .listen(3000, () => {
    console.log("http://localhost:3000");
  });
但是通过设置last-modified也存在缺陷,主要有两方面的缺陷 1 首先它是根据最后的修改时间戳进行判断的,虽然请求的文件资源进行了编辑,但是内容并没有发生任何变化,时间戳也会更新,从而导致协商缓存时候关于有效性的判断验证为失败,需要重新进行完整的资源请求,会造成网络资源带宽的浪费 2 文件资源修改的时间戳的单位是秒,如果文件修改的速度非常快,假设在几百毫秒内完成,那么通过时间戳的方式验证缓存的有效性是无法识别出该文件资源的更新的

为了解决以上问题,http1规范新增了一个ETag的头信息去弥补这个不足。
其内容主要是服务器为不同资源进行哈希运算生成的一个字符串,该字符串类似于文件指纹,只要文件内容编码存在差异,对应的ETag标签值就会不同
因此可以使用ETag对文件资源进行更准确的变化感知
在这里演示这个功能需要引入etag

在这里插入代码片
const http = require("http");
const fs = require("fs");
const url = require("url");
const etag = require("etag");
http
  .createServer((req, res) => {
    // res.end("hello");
    // console.log(url.parse(req.url));  返回一个对象
    console.log(req.method, req.url);
    let { pathname } = url.parse(req.url);
    if (pathname == "/") {
      const data = fs.readFileSync("./index.html");
      res.end(data);
    } else if (pathname == "/img/qq.png") {
      const data = fs.readFileSync("./img/qq.png");
      const ifNoneMatch = req.headers["if-none-match"];
      const etagContent = etag(data);
      if (ifNoneMatch === etagContent) {
        res.statusCode = 304;
        res.end();
        return;
      }

      res.setHeader("Cache-Control", "no-cache");
      res.setHeader("etag", etagContent);
      res.end(data);
    }
  })
  .listen(3000, () => {
    console.log("http://localhost:3000");
  });

不像在强制缓存中cache-control可以完全替代expires的功能,在协商缓存中,Etag并非last-modified的替代方案而是一种补充方案,它也存在一定的缺陷。因为服务器需要对文件资源的Etag需要付出额外的计算开销,如果资源的尺寸较大,那么生成ETag的过程就会影响服务器的性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值