HTTP 缓存控制
前端缓存主要分为 HTTP 缓存和浏览器本地存储。
其中 HTTP 缓存是在 HTTP 请求传输时用到的缓存,主要在服务器代码上设置;而浏览器本地存储则主要由前端开发在前端 JS 上进行设置。
缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。
一、什么是 HTTP 缓存
HTTP 缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取资源。
常见的 HTTP 缓存只能缓存 GET 请求响应的资源,对于其他类型的响应则无能为力,所以后续说的请求缓存都是指 GET 请求。
HTTP 缓存都是从第二次请求开始的。
- 第一次请求资源时,服务器返回资源,并在 respone header 头中回传资源的缓存参数;
- 第二次请求时,浏览器判断这些请求参数,命中强缓存就直接 200,否则就把请求参数加到 request header 头中传给服务器,看是否命中协商缓存,命中则返回 304,否则服务器会返回新的资源。
HTTP 缓存有以下好处:
- 减少了冗余的数据传输,节省了网费;
- 缓解了服务器的压力,大大提高了网站的性能;
- 加快了客户端加载网页的速度。
二、浏览器的缓存机制
浏览器第一次向服务器发起请求并拿到请求结果后,会根据响应报文中 HTTP 头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中,过程如下:
根据缓存标识和缓存结果来决定使用强缓存、协商缓存还是直接向服务器发起请求,主要有以下三种情况:
1、不存在缓存标识和缓存结果
不存在缓存标识和缓存结果,则强制缓存失效,直接向服务器发起请求:
2、存在缓存标识和失效的结果
存在缓存标识和缓存结果,但该结果已失效,则强制缓存失效,使用协商缓存:
3、存在缓存标识和未失效的结果
存在缓存标识和缓存结果,且该结果尚未失效,则强制缓存生效,使用强缓存,直接返回该结果:
三、HTTP 缓存的分类
根据是否需要重新向服务器发起请求来分类,可分为强缓存和协商缓存;
根据是否可以被单个或者多个用户使用来分类,可分为私有缓存和共享缓存。
强缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。
下面是强缓存和协商缓存的一些对比:
强缓存 | 协商缓存 | |
---|---|---|
缓存存放位置 | 本地浏览器 | |
HTTP 状态码 | 200 | 304 |
谁来决定 |
|
|
操作是否有效 |
|
|
四、强制缓存
强缓存指的是在缓存数据未失效的情况下(即 Cache-Control 的 max-age 没有过期或 Expires 的缓存时间没有过期),会直接使用浏览器的缓存数据,不会再向服务器发送任何请求,这种方式页面的加载速度是最快的,性能也是很好的。
强缓存如果服务器端的资源修改了,页面上是拿不到的,因为它不会再向服务器发请求了。这时就需要 Ctrl + F5 强制刷新页面了。
强缓存生效时,HTTP 状态码为 200。
跟强缓存相关的 header 头属性有 Pragma / Cache-Control / Expires,详情如下:
header 属性 | 可选值 | 优先级 | 优缺点 |
---|---|---|---|
Pragma | no-cache:不直接使用缓存,根据新鲜度来使用缓存 | 高 |
|
Cache-Control |
| 中 |
|
Expires | GMT 时间 | 低 |
|
注意:强缓存情况下,只要缓存还没过期,就会直接从缓存中取数据,就算服务器端有数据变化,也不会从服务器端获取了,这样就无法获取到修改后的数据。
解决办法:在修改后的资源加上随机数,确保不会从缓存中取。例如:
http://www.leophen.cn/kim/common.css?v=22324432
http://www.leophen.cn/kim/common.2312331.css
五、协商缓存
协商缓存指的是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识决定是否使用缓存的过程。
这里携带的缓存标识指的是 Etag 和 Last-Modified,服务器校验后如果资源没有修改,则返回 304 状态码,浏览器直接使用缓存。
如果资源有更新则返回 200 状态码,服务器就会返回更新后的资源并且将缓存信息一起返回。
跟协商缓存相关的 header 头属性有 ETag / If-Not-Match 、Last-Modified / If-Modified-Since,请求头和响应头需要成对出现,详情如下:
header 属性 | 可选值 | 优先级 | 优缺点 |
---|---|---|---|
ETag / If-Not-Match | 校验值 | 高 |
|
Last-Modified / If-Modified-Since | GMT 时间 | 低 |
|
注意:应尽量减少 304 的请求,因为协商缓存每次都会与后台服务器进行交互,所以性能上不是很好。从性能上来看尽量多使用强缓存。
六、如何使用 HTTP 缓存
1、html 页面缓存的设置
html 页面缓存的设置主要是嵌入 <meta>
标签。
- html 设置缓存如下:
<!-- 仅 IE 才识别的标签 -->
<meta http-equiv="Expires" content="Mon, 20 Aug 2018 23:00:00 GMT" />
<!-- 主流浏览器识别的标签 -->
<meta http-equiv="Cache-Control" content="max-age=7200" />
2、静态资源的缓存
- 静态资源的缓存一般是在 web 服务器上配置的。
3、不想使用缓存的方式
- Ctrl + F5 强制刷新,会直接向服务器提取数据。
- F5 刷新,默认加上 Cache-Control:max-age=0,走协商缓存。
- 在 IE 下不想使用缓存的做法:工具 -> Internet 选项 -> 常规 -> 浏览历史记录 设置选择“从不”,然后保存。最后点击“删除”把 Internet 临时文件都删掉(IE 缓存的文件就是 Internet 临时文件)
- html 页面禁用缓存的设置如下:
<!-- 仅 IE 才识别的标签,不一定会在请求字段加上 Pragma,但会让当前页面每次都发新请求 -->
<meta http-equiv="pragma" content="no-cache">
<!-- 仅 IE 才识别的标签,仅作为知会 IE 缓存时间的标记,不能在请求或响应报文中找到 Expires 字段 -->
<meta http-equiv="expires" content="0">
<!-- 主流浏览器识别的标签 -->
<meta http-equiv="cache-control" content="no-cache">