【Http原理】请问 HTTP 是怎么进行缓存的?

HTTP 缓存是一块重要的内容,这是作为一个前端工程师必须要掌握的优化技能,也能让自己明白自己的工作,此次主要分了几个点进行总结

  • 缓存策略
  • 缓存首部
  • 缓存类型
  • 缓存计算时间
  • 缓存资源类型
  • 设置缓存

浏览器缓存策略

浏览器对于请求资源,拥有一系列成熟的 缓存策略

1、存储策略

确定 HTTP 响应内容是否可以被客户端缓存,可以被哪些客户端缓存

相关首部 设置

Cache-Control:no-cache Pragma:no-cache

2、过期策略

根据存储时间判断本地缓存是否过期,是否需要重新请求

相关首部 设置

Cache-control:max-age=100,min-fresh=100,max-stale=100 Expires : Mon, 13 Aug 2018 03:40:08 GMT

3、协商策略

重新向服务器发起验证,查证缓存是否过期

相关首部 设置

if-Modified-Since, if-unmodified-since, last-modified if-match, if-none-match, etag

缓存相关首部

1.Cache-Control

霸道总裁:其他设置有相同,一律覆盖

杂交规则:可以同时设置很多种值,包含存储策略,过期策略

Cache-Control:max-age=10,min-fresh=10,max-stale=10

max-age

覆盖默认时间,缓存 10 s

max-stale

增加默认过期时间,在 10 s内,缓存可以过期

min-fresh

减少默认过期时间,最后 10 s,缓存不能过期

Cache-Control 还有很多其他值,但是我过滤了一些

Cache-Control:no-cache,no-store,must-revalidate

public

被客户端和 代理服务器 缓存

private

只被客户端缓存,代理服务器不缓存

no-cache

防止从缓存中返回过期的资源,缓存会向源服务器进行有效确认后处理资源其实不是不让你缓存到本地,而是让你每次请求都不会马上本地缓存获取,而是确认一遍

no-store

请求和响应都不缓存

only-if-cached

要求 只返回已经缓存的资源,不用访问网络,无缓存就返回504

must-revalidate

可缓存,但是必须向原服务器确认

2.Pragma

http1.0 字段,现在为了向后兼容,也是指定缓存机制

Pragma:no-cache

3.Expires

http1.0 字段,为了向后兼容,指定 缓存时间

Expires: Mon, 13 Aug 2018 03:40:08 GMT

4.Last-Modified

资源最后一次修改时间,以此判断资源是否更新

Last-Modified: Thu, 09 Aug 2018 10:42:13 GMT

5.Etag

资源唯一标志,修改之后,标志会相应更新,以此判断资源是否更新

浏览器根据Etag 值缓存数据, 节省带宽

Etag 比 Last-Modified 级别要高

ETag:"fcb82312d92970bdf0d18a4eca08ebc7efede4fe"

6.If-Modified-Since,If-Unmodified-Since

主要也是为了判断资源是否更新过

两个首部的值都是是上次响应收到的 Last-Modified 的值

If-Modified-Since

If-Modified-Since 时间后 被修改,返回200

没有被修改,返回304

If-UnModified-Since

If-UnModified-Since 时间后 未修改,返回 200

被修改,返回 412 Precondition failed 预处理错误

主要用于断点续传,肯定要保证文件没有修改

7.If-Match, If-None-Match

主要也是为了判断资源是否更新过

两个首部的值都是是上次响应收到的 Etag 值

If-Match

如果和 请求资源的 ETag 一样,返回200

如果不一样,返回 412

If-None-Match

如果和 请求资源的 ETag不一样,返回 200

如果一样,返回304

缓存类型

强缓存

一旦命中强缓存,浏览器就不会发送请求,而是直接读取缓存。

Chrome 下是 200 OK (from disk cache) 或者 200 OK (from memory cache)

只要存在缓存,而且 Cache-Control 和 Expires 没有过期,那么都能命中缓存

协商缓存

缓存过期了,需要重新请求资源,有两种做法

1、判断 ETag 是否改变

1、浏览器把上次响应的 Etag 的值,填入这次请求的 If-None-Match

2、服务器收到请求,拿 If-None-Match 字段 和 服务器资源的 Etag 对比,若相同,命中协商缓存,返回304

2、判断 Last-MOdified 是否改变

1、浏览器把上次响应的 Last-Modified,填入这次请求的 If-Modified-Since

2、服务器收到请求,拿 If-Modified-Since 和 服务器资源的 Last-Modified 比较,如果相同,命中协商缓存,返回304

304 到底有什么用?? 当客户端缓存了目标资源,但是不确定是否是最近的版本,会发一个条件请求,附带上 条件首部 服务器拿到首部,判断出客户端的资源是否是最新的 如果是最新的,返回304,但是没有响应体,客户端收到304,就会从缓存中读取对应的值 如果不是最新的,返回200,返回最新的内容,客户端使用新的响应体 覆盖 旧的响应体 可以节省网页的打开时间,有机会省去整个响应体的发送 条件请求的触发条件

  • 资源在客户端过期
  • 用户手动刷新,不包括强刷

缓存资源类型

1、文件可以缓存,比如 js、css、json

2、post 无法缓存,get 请求可以缓存

3、还有其他的我不知道.......

通过测试,可以知道,缓存放在两个位置

一个是 disk,一个是 memory

而同样是 reset.css,通过 link 引入,和 通过 ajax 请求,缓存存放的位置是不一样的

下面是 link 引入reset.css

下面是 ajax 引入reset.css

而 ajax 请求接口的数据,也是放在 disk

所以,可以得出

1、ajax 请求的缓存都放在 disk

2、 页面引入的 js、css 都放在 memory

缓存过期时间计算

响应返回 Cache-Control:

当同时添加 max-stale,min-fresh,max-age,他们之间相互独立

并不会谁一定覆盖谁,而是看谁最后计算得到的 保存时间最短,到最后使用谁

比如 资源在 今天 8:00:00 缓存,今天8:00:50 过期,也就是说默认 缓存时间为 50s

现在,我们添加一个 缓存时间变量 cache_time

第一种设置

max-age=10,那么 cache_time= 10

max-stale=5,那么 cache_time= 50+5 = 55

max-fresh=2,那么 cache_time= 50-5 = 45

最后会使用 max-age 作为 缓存时间,因为最短

第二种设置

max-age=100,那么 cache_time= 100

max-stale=5,那么 cache_time= 50+5 = 55

max-fresh=2,那么 cache_time= 50-5 = 45

最后会使用 max-fresh 作为 缓存时间,因为最短

原来浏览器喜欢短的......

响应返回 Expires

设定一个具体的时间

Expires: Mon, 13 Aug 2018 03:40:08 GMT

Expires 时间到了之后,缓存就过期了

默认启发式缓存日期算法

当 没有设置,Cache-Control 和 Expires 的时候,就使用默认算法

取 响应头的 Date 减去 Last-Modified ,然后乘以 10% 作为缓存时间

var cacheTime = (new Date(date)-new Date(last-modified) )/10 var Expires_value = new Date(Date_value + cacheTime);

最后 Expires_value 就是缓存到期的时间

设置缓存

是否缓存

Pragma:no-cache 或者 Cache-Control:no-cache

设置缓存时间

Expires: Mon, 13 Aug 2018 03:40:08 GMT

Cache-Control: max-age=10.....(其他略)

禁用缓存

1、请求头设置

Cache-Control: no-cache, no-store, must-revalidate

2、资源设置版本号

reset_041c3208.css

3、页面 head 加入 meta

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>

原文发布于微信公众号 - 神仙朱(skying-zhu)

原文发表时间:2018-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券