HTTP资源缓存精讲 & QA

什么是 HTTP 缓存

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术

缓存的基础是建立在两者文件路径完全相同的情况下

http缓存主要针如css,js,图片等更新频率不大的静态文件

缓存技术的优点

  • 减少重复数据请求,避免通过网络再次加载资源,节省流量
  • 降低服务器压力,提升网站性能
  • 加快客户端加载网页的速度,提升用户体验

缓存类型

强缓存

不需要发送请求到服务端,直接读取浏览器本地缓存

由响应头中的 Cache-Control 或者 Expires 字段控制,表示资源的缓存有效时间

  • Expires 是 http 1.0 的规范,值是一个 GMT 格式的时间点字符串(expires: Thu, 17 Mar 2022 07:19:55 GMT)。这个时间点代表资源失效时间,如果之后的请求时间戳在这个时间戳之前,则命中强缓存。如果服务器时间和客户端时间偏差较大时,会导致缓存混乱。

  • Cache-Control 是 http1.1 的规范,使用 max-age 来设置资源可以被缓存多长时间,值是一个相对时间,相对于用户请求时间,单位为秒。用户请求时间 + max-age 即为强缓存有效时间,在有效时间内重复请求,会命中强缓存。 Cache-Control 可设置的其他值:

    • no-cache : 浏览器缓存了数据,但是再次请求时,是不直接使用强缓存,强制使用协商缓存,即每次请求都必须向服务器发送
    • no-store : 直接禁止浏览器缓存数据,每次请求资源都会向服务器获取完整的资源
    • public : 可以被所有用户缓存,包括终端用户和 cdn 等中间件代理服务器
    • private : 只能被终端用户的浏览器缓存
    • s-maxage : 和 max-age 一样,不过它只针对代理服务器而言
  • 强缓存优先级

max-ageExpires 优先级高,并存时,采用 max-age

协商缓存(对比缓存)

最终由服务器决定是否使用缓存,即客户端获取资源时,会向服务器发送请求,用服务器判断是否使用缓存数据。

协商缓存下如果命中缓存,服务器端响应的状态码为304(not modified)。

两组规则: Last-Modified / If-Modified-SinceETag / If-None-Match

  • Last-Modified / If-Modified-Since

    1、服务器响应浏览器的响应时,会在响应头里添加一个字段 Last-Modified ,值为资源的最后修改时间

    image.png

    2、浏览器之后再请求时,会在请求头添加字段 If-Modified-Since , 值为服务器上一次响应的 Last-Modified

    image.png

    3、服务器会对比源资源最后修改时间和web请求头里的 If-Modified-Since 字段值。如果大于 If-Modified-Since ,这说明资源有更新,缓存已失效,浏览器则不能再使用之前的缓存副本,返回完整的资源数据并响应码为 200 ;如果相等,则表明资源未失效,响应头信息中状态码为 304 ,响应消息体中没有数据

    image.png

  • ETag / If-None-Match

    1、服务器响应浏览器的响应时,会在响应头里添加一个字段 ETag,值为资源的一个唯一标识(生成规则实现方式不一,由具体的服务器决定)

    image.png

    2、浏览器之后再请求时,会在请求头添加 If-None-Match,值为服务器上一次响应的 ETag

    image.png

    3、服务器比对源资源的 ETag 是否和 web 请求头的 If-None-Match 字段值一致。不一致则说明文件有更新,本地缓存已失效,响应完整的资源数据并响应码为 200 ;如果一致,则命中协商缓存,响应码为 304

    image.png

    • 协商缓存两组规则的优先级

    Last-Modified / If-Modified-SinceETag / If-None-Match 并存时,使用 ETag / If-None-Match

HTTP 缓存的流程图

image.png

Q & A

1、既然已经存在 Last-Modified / If-Modified-Since,为什么规范里由引入了 ETag / If-None-Match ?

ETag 值都是由服务器为每一个资源生成的唯一标识串,只要资源有变化就这个值就会改变。

HTTP1.1ETag 来判断请求的文件是否被修改,主要为了解决 Last-Modified 无法解决的一些问题:

1、一些文件也许会做周期性的更改,但是他的内容并不更改(仅仅改变的修改时间),这个时候并不希望客户端认为这个文件被修改了重新GET

2、某些文件修改非常频繁,1秒内修改了N次,If-Modified-Since 能检查到的粒度是秒级的,这种判断无法修改

3、某些服务器不能精确的得到文件的最后修改时间

为此,HTTP1.1 引入了 ETag 。但标准并没有规定ETag的内容是什么或者说要怎么实现,唯一规定的是`ETag 需要放在双引号内。

max-ageExpires 的区别

1、max-agehttp 1.1 的属性, Expireshttp 1.0 的属性,为了做到向下兼容,一般写两个。但在 http 1.1 的环境下, max-ageExpires 优先级高

2、max-age 是相对过期时间, Expires 是绝对过期时间。 max-age 在浏览器成功缓存文件后,只需相对成功之后的多长时间不再发起请求就好了,而 Expires 总是需要服务器返回一个精准的 GMT 格式的日期,并以这个日期为标准来判断缓存是否过期。本地时间和服务器时间有较大偏差时,缓存就会不准确

单页面缓存应用实践

  • html 文件:应用唯一入口,也是加载资源的唯一入口,所以建议 html 文件禁止使用缓存 Cache-Control: no-store,保证用户请求到的 html 文件永远为最新的

  • JS、CSS 文件:项目基本使用 webpack 等构建工具,资源名称由 HASH值 进行标识,资源更新时,则 HASH值 会发生改变,文件路径改变,故不再满足缓存条件,首次加载时必然请求服务器。所以缓存策略可以将 max-age 配置一个绝对大的值

  • image、media 等媒体资源:根据网站实际情况做缓存策略

provisional headers are shown (显示临时报头)

image.png

上图表示:真正的请求并没有被发送,出现此种情况的原因是真正的Header只有在服务器端响应的时候更新。显示临时报文的几种情况:

1、命中强缓存,请求未发出

2、跨域,请求被浏览器拦截

3、请求被浏览器插件拦截

4、服务器出错或者超时,服务器端没有响应

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享