前端HTTP缓存

Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。其中前端比较关心的是浏览器缓存,包括今天要说的HTTP缓存和前面说过的cookie、localStorage等存储。(资源缓存仅针对get请求,post、put、delete等行为性操作无缓存)。

HTTP缓存分为强缓存和协商缓存。通过特殊的HTTP中的cache-control首部和expries首部,说明文档是否过期,浏览器二次请求相同资源时,进行比较,没有过期则为强缓存。过期则核对是否修改,但是缓存过期仅代表需要进行核对,而不一定是资源有了差异,客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存,这便是协商缓存。

 

 from-cache:

  • 200:缓存命中
  • 304:再匹配未修改(not modified)

强缓存

Cache-Control和Expires

强缓存利用Expires和Cache-Control两个字段来控制。expires:是缓存过期时间(即资源过期时间),是个绝对值。所以如果客户端更改时间,会导致缓存混乱。所以http1.1增加了cache-control,由多个字段组合而成,其中max-age 字段,它是一个相对的时间。

  • Cache-Control是HTTP1.1中新增的响应头,Expires是HTTP1.0中的响应头
  • Expires指定的是具体的过期日期而不是秒数,Cache-Control使用的是相对时间
  • Cache-Control和Expires同时使用的话,Cache-Control会覆盖Expires

Cache-Contro相关属性

max-age(单位为s)

指定设置缓存最大的有效时间,当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。

public

指定响应可以在代理缓存中被缓存,于是可以被多用户共享。如果没有明确指定private,则默认为public。

private

响应只能在私有缓存中被缓存,不能放在代理缓存上。对一些用户信息敏感的资源,通常需要设置为private。

no-cache

表示必须先与服务器确认资源是否被更改过(依靠If-None-Match和Etag),然后再决定是否使用本地缓存。

no-store

绝对禁止缓存任何资源,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的资源。通常用于机密性资源。

 协商缓存

浏览器或代理缓存中缓存的资源过期了,并不意味着它和原始服务器上的资源有实际的差异,仅仅意味着到了要进行核对的时间了。这种情况被称为服务器再验证,也就是协商缓存:

  • 如果资源发生变化,则需要取得新的资源,并在缓存中替换旧资源。
  • 如果资源没有发生变化,缓存只需要获取新的响应头,和一个新的过期时间,对缓存中的资源过期时间进行更新即可。

HTTP1.1推荐使用的验证方式是If-None-Match/Etag,在HTTP1.0中则使用If-Modified-Since/Last-Modified。

If-None-Match/Etag

Etag是指根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生,第一次请求响应头会带上ETag: abcd,之后的请求中带上 If-None-Match: abcd。浏览器会将这串字符串传回服务器,验证资源是否已经修改,返回 304 或 200。

If-Modified-Since与Last-Modified

Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。这两个是HTTP1.0中用来验证资源是否过期的请求/响应头,这两个头部都是日期,验证过程与Etag类似,这里不详细介绍。使用这两个头部来验证资源是否更新时,存在以下问题:

  • 有些文档资源周期性的被重写,但实际内容没有改变。此时文件元数据中会显示文件最近的修改日期与If-Modified-Since不相同,导致不必要的响应。
  • 有些文档资源被修改了,但修改内容并不重要,不需要所有的缓存都更新(比如代码注释)

如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。

last-modified 和 Etag 区别

  • 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
  • Last-modified 只能精确到秒。
  • 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
  • Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request。

应用

使用缓存的原因:

  • 冗余的数据传输
  • 带宽瓶颈
  • 瞬间拥塞
  • 距离时延

缓存场景:

  • CSS文件、js文件、html文件
  • 图标、图片
  • 供下载的附件

缓存时间:

  • 不经常改变的文件,设置较大的max-age,一般设置max-age=31536000(标准中规定 max-age 的值最大不超过一年,所以设成 max-age=31536000)
  • 经常需要变动的文件,Cache-Control: no-cache / max-age=0

 

posted on 2019-09-24 08:56  紅葉  阅读(292)  评论(0编辑  收藏  举报