# 浏览器缓存机制(HTTP 缓存机制)
说起浏览器缓存可能会想到 coockie
, localStorage
等。这里会介绍的缓存是指 HTTP缓存机制。
本文内容:
- 介绍
HTTP
缓存 - 强制缓存,
Expires
和Cache-Control
- 协商缓存,
Etag
和last-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 请求:
- 在浏览器本地查找是否存在该资源
- 如果不存在,向服务器发送 http 请求
- 如果过存在,返回本地的资源,并该资源缓存到本地
在这缓存过程分为两种,强制缓存和协商缓存。下面具体介绍。
# 3. 强制缓存
强制缓存是指,从浏览器的缓存中查找数据,有三种情况:
- 查找缓存,不存在,向服务器发送请求
- 查找缓存,过期了,向服务器发送请求
- 查找缓存,没有过期,返回缓存内容
怎么知道过期的呢,又怎么缓存呢?
服务器给浏览器发送资源时,给资源标注好,这个数据需不需要缓存到本地,这个标注是浏览器头部Expires 和 Cache-Control。
(1)Expires
Expires
的值为缓存过期的时间,是 HTTP/1.0
控制网页缓存的字段。比如,2021.10.1 00:00 类似这种,如果第二次请求该资源,并且10月1号前,那么直接返回本地缓存的内容,说明没有过期。
在 HTTP/1.1
中 Expires
被 Cache-Control
代替,原因是本地时间可能会有错误。
(2)Cache-Control
在 HTTP/1.1
中,缓存规则是 Cache-Control
的字段,它有以下字段:
- public:可缓存所有内容,客户端和代理服务器
- private:可缓存所有内容,只有客户端
- no-cache:客户端缓存,是否使用协商缓存来验证
- no-store:不会缓存,不使用强制缓存,协商缓存
- max-age=???:缓存内容 ??? 后失效
Expires
和 Cache-Control
两个字段同时存在时,优先使用 Cache-Control
。
# 4. 协商缓存
协商缓存是,本地缓存过期,向服务器发送 HTTP
请求,这是服务器可能返回两种状态码:200
或 302
,下面分别讨论两种情况:
(1)302
如果请求某个资源返回 302
状态码,说明协商缓存生效。具体过程如下:
- 发送
HTTP
请求,先去找本地缓存 - 本地缓存中的内容过期了,返回过期的标识
- 向服务器发送请求,携带过期标识
- 服务器检查,看这段时间内资源没有变化,返回
302
,没有内容 - 浏览器使用本地缓存的内容。
(2)200
整个过程跟 301
差不太多,具体过程如下:
- 发送
HTTP
请求,先去找本地缓存 - 本地缓存中的内容过期了,返回过期的标识
- 向服务器发送请求,携带过期标识
- 服务器检查,看这段时间内资源有变化,返回
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. 总结
参考: