# 浏览器缓存机制(HTTP 缓存机制)

说起浏览器缓存可能会想到 coockie, localStorage 等。这里会介绍的缓存是指 HTTP缓存机制。

本文内容:

  • 介绍 HTTP 缓存
  • 强制缓存,ExpiresCache-Control
  • 协商缓存,Etaglast-Modified

# 1. 概述

先介绍一下,HTTP 常见状态码

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误
状态码 描述
1** 信息,请求已经接受,处理中
2** 成功, 200
3** 重定向,常见301(永久移动),302(临时移动),304(未修改,内容为空)
4** 客户端错误,常见 404 (找不到响应文件)
5** 服务端错误,501(服务器不支持请求的功能)

HTTP缓存简单地说,就是当你两次请求某一个网站时,浏览器第一次请求时,会缓存一些数据,第二次请求同样数据时,直接回复缓存的内容,第二次不会发送 HTTP 请求。

这样第二次请求时的时间会大大缩短,大大提高了用户体验,也节省了宽带。

不过这个过程中会有很多情况,比如,同样的内容,浏览器第一次请求时缓存到本地了,之后服务器改变了这个资源,第二次请求直接返回缓存,这导致用户获取不到最新资源。所以浏览器缓存有一些规则,下面我们深入介绍。

# 2. 发送 HTTP 请求的过程

因为缓存在 HTTP 请求中产生的,所以先分析发送一个 HTTP 请求发送的过程。

发送一个 HTTP 请求:

  1. 在浏览器本地查找是否存在该资源
  2. 如果不存在,向服务器发送 http 请求
  3. 如果过存在,返回本地的资源,并该资源缓存到本地

图面

在这缓存过程分为两种,强制缓存协商缓存。下面具体介绍。

# 3. 强制缓存

强制缓存是指,从浏览器的缓存中查找数据,有三种情况:

  • 查找缓存,不存在,向服务器发送请求
  • 查找缓存,过期了,向服务器发送请求
  • 查找缓存,没有过期,返回缓存内容

怎么知道过期的呢,又怎么缓存呢?

服务器给浏览器发送资源时,给资源标注好,这个数据需不需要缓存到本地,这个标注是浏览器头部Expires 和 Cache-Control

(1)Expires

Expires 的值为缓存过期的时间,是 HTTP/1.0 控制网页缓存的字段。比如,2021.10.1 00:00 类似这种,如果第二次请求该资源,并且10月1号前,那么直接返回本地缓存的内容,说明没有过期。

HTTP/1.1ExpiresCache-Control 代替,原因是本地时间可能会有错误。

(2)Cache-Control

HTTP/1.1 中,缓存规则是 Cache-Control 的字段,它有以下字段:

  • public:可缓存所有内容,客户端和代理服务器
  • private:可缓存所有内容,只有客户端
  • no-cache:客户端缓存,是否使用协商缓存来验证
  • no-store:不会缓存,不使用强制缓存,协商缓存
  • max-age=???:缓存内容 ??? 后失效

ExpiresCache-Control 两个字段同时存在时,优先使用 Cache-Control

# 4. 协商缓存

协商缓存是,本地缓存过期,向服务器发送 HTTP 请求,这是服务器可能返回两种状态码:200302,下面分别讨论两种情况:

(1)302

如果请求某个资源返回 302 状态码,说明协商缓存生效。具体过程如下:

  • 发送 HTTP 请求,先去找本地缓存
  • 本地缓存中的内容过期了,返回过期的标识
  • 向服务器发送请求,携带过期标识
  • 服务器检查,看这段时间内资源没有变化,返回 302没有内容
  • 浏览器使用本地缓存的内容。

302

(2)200

整个过程跟 301 差不太多,具体过程如下:

  • 发送 HTTP 请求,先去找本地缓存
  • 本地缓存中的内容过期了,返回过期的标识
  • 向服务器发送请求,携带过期标识
  • 服务器检查,看这段时间内资源有变化,返回 200内容携带新的资源
  • 浏览器使用本地缓存的内容。

200

协商缓存控制的字段有一下几个,我们已经知道,需要向服务器发送本地缓存的时间等信息:

如果服务器查看请求中有 If-None-Match ,与自己生成的 Etag 比较,如果相同,说明没有变化,返回 302,不相同重新发送,返回 200

  • Etag:服务器 => 浏览器,返回当前资源文件的一个唯一标识(由服务器生成)
  • If-None-Match:浏览器=>服务器,再次请求时,返回 Etag

如果服务器查看请求中有 last-Modified ,与自己生成的 If-Modified-Since 比较,如果相同,说明没有变化,返回 302,不相同重新发送,返回 200

  • last-Modified:服务器 => 浏览器,返回该资源文件在服务器最后被修改的时间
  • If-Modified-Since: 浏览器=>服务器,再次请求时,返回 last-modified

需要注意的是,Etag 的优先级高于 last-Modified

# 5. 总结

总结

参考:

更新时间: 12/26/2021, 1:44:08 PM