前端面经 http缓存机制:强缓存(expires和cache-control)、协商缓存(Etag/If-None-Match和Last-Modified/If-Modified-Since)

关于强缓存和协商缓存

为什么需要缓存机制

缓存机制的定义: 浏览器在用户的本地磁盘存储了用户最近请求的资源。当用户再次请求同一资源时,浏览器直接从本地磁盘读取资源即可。

  • 减少多余的数据传输
  • 减轻服务器端的负担
  • 加快客户端加载网页的速度,提升用户体验

缓存的过程

第一次缓存

浏览器发送第一次请求时,本地是没有缓存的;
故向服务器发送请求;
服务器响应请求
前端面经 http缓存机制:强缓存(expires和cache-control)、协商缓存(Etag/If-None-Match和Last-Modified/If-Modified-Since)
图源于网络

注意:在第一次请求后,服务器会返回两个关键标识给客户端

  • Last-Modified:最后的修改时间
  • Etag:唯一标识一个文件

再次请求

前端面经 http缓存机制:强缓存(expires和cache-control)、协商缓存(Etag/If-None-Match和Last-Modified/If-Modified-Since)
图源于网络

对照上图来看,当浏览器再次发送请求时,有如下步骤:

  • 浏览器请求某一资源时,会先获取该资源的header信息。根据header信息中的expires和cache-control 去判断该资源是否过期。若未过期,是强缓存,则直接在缓存中获取资源,不向服务器发送请求。
  • 如果过期了,浏览器只能再给服务器发送请求。客户端会将第一次请求时,服务器所给的Etag和Last-Modified,分别赋给If-None-Match和If-Modified-Since。服务器对比客户端Etag/If-None-Match和Last-Modified和If-Modified-Since,综合考虑要返回200还是304状态字。
  • Etag/If-Not-Modified和Last-Modified/If-Modified-Since,如果请求内容是最新的,返回304,客户端继续使用本地缓存;如果不是最新的,返回200。

强缓存(Expires/Cache-Control)

强缓存是利用http头的Expires和Cache-Control两个字段来控制的。

Expires

Expires值代变这个资源的失效时间。即只要发送的请求在这个时间之前,那么资源是有效的,可以使用本地缓存。即本地缓存还没有过期,资源尚未失效。

Cache-Control

Cache-Control:max-age = 3600,代表资源的有效期是3600秒

Cache-Control有几个常用的可使用值:

  • max-age :是一个相对时间,用于计算资源的过期时间
  • no-cache:不使用本地缓存,跳过强缓存
  • no-store:禁止使用缓存,即没有强缓存也没有协商缓存。每次请求数据都会向服务器发送请求,然后完整地下载资源
  • public:可以被所有用户缓存,包括终端用户和CDN等中间代理服务器
  • private:只能被终端用户缓存

注意: 强缓存中,当Expires和Cache-Control同时出现时,Cache-Control的优先级更高!!

协商缓存(Etag/If-None-Match和Last-Modified/If-Modified-Since)

协商缓存需要两组标识去判断

Last-Modified/If-Modified-Since

上文已经说过,当第一次访问请求的时候,服务器会返回一个最后修改时间Last-Modified给浏览器。当浏览器再次请求时,会在request的header上附加一个If-Modified-Since的header,这个If-Modified-Since就是上一次请求返回的Last-Modified的值。
服务器拿着浏览器发送过来的If-Modified-Since与服务器上的最后修改时间进行比对。

  • 若相同,说明资源是最新的,没有改动,则返回304,浏览器读取本地缓存。
  • 若不相同,说明资源被修改了,返回200,服务器返回新的资源。(当然也会返回新的Last-Modified)

Etag/If-None-Match

与Last-Modified/If-Modified-Since同理。
只不过Etag是资源的唯一标识,如果资源发送变化,那Etag就会变化。

不同的是,服务器返回304时,不会返回新的Last-Modified,但是会返回新的Etag(因为Etag重新生成了)。

为什么明明依靠Last-Modified,就可以判断资源是否有修改,还需要一个Etag??

Etag的必要性:

  • 一些文件会周期性更改,只是改变的只是修改时间但并不改变内容。我们并不希望这种情况会被客户端认为,资源被修改了。
  • 一些文件的修改非常频繁。频繁到Last-Modified与If-Modified-Since都不能检测到它发生了修改。
  • 某些服务器不能精确地得到文件的最后修改时间

需要注意的是:

Etag/If-None-Match 和 Last-Modified/If-Modified-Since 成对出现,一起作用。但是服务器会优先验证Etag,一致地情况下再进一步验证Last-Modified。综合考虑后,再决定是要返回304还是200.

上一篇:【Python】半次元COS图爬取


下一篇:c++ 判断系统类型