http缓存

以平时打开百度为例。我们在network里面看到两种不同的状态:from memory cachefrom disk cache,前者指缓存来自内存,后者指缓存来自硬盘。而控制缓存存放位置的,不是别人,就是我们在服务器上设置的Etag字段。在浏览器接收到服务器响应后,会检测响应头部(Header),如果有Etag字段,那么浏览器就会将本次缓存写入硬盘中。



在验证是否有缓存,会分两条线路:

  • 强缓存: 当浏览器再次访问某个 URL 时,会先获取资源的 header 信息,判断是否命中强缓存
    (cache-control和expires)
    ,如命中,直接从缓存获取资源,包括响应的 header 信息
    (请求不会和服务器通信)。
  • 协商缓存:如没有命中 强缓存 ,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的 header信息
    (Last-Modified/If-Modified-Since和Etag/If-None-Match)
    ,由服务器根据请求中的相关 header 信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应 header 信息更新缓存中的对应 header 信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容。

缓存策略获取资源形式状态码发送请求到服务器
强缓存从缓存取200(from memory cache)否,直接从缓存取
协商缓存从缓存取304(not modified)是,通过服务器来告知缓存是否可用


强缓存:cache-control(优先级最高)和expires

cache-control: max-age=number ,这是 http1.1 时出现的 header 信息,相对时间。主要是利用该字段的 max-age 值来进行判断,它是一个相对值;资源第一次的请求时间和 Cache-Control 设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则未命中, cache-control 除了该字段外,还有下面几个比较常用的设置值:

  • no-cache: 不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在 ETag ,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
  • no-store: 直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
  • public: 可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。
  • private: 只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。


协商缓存:Last-Modified/If-Modified-Since 和 Etag/If-None-Match

协商缓存都是由浏览器和服务器协商,来确定是否缓存,协商主要通过下面两组 header 字段,这两组字段都是成对出现的,即第一次请求的响应头带上某个字段

Last-Modified 或者 Etag

,则后续请求会带上对应的请求字段

If-Modified-Since 或者 If-None-Match

,若响应头没有 Last-Modified 或者 Etag 字段,则请求头也不会有对应的字段。


Last-Modified/If-Modified-Since

二者的值都是 GMT 格式的时间字符串,具体过程:

  • 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在 responeheader 加上 Last-Modified字段,这个 header 字段表示这个资源在服务器上的最后修改时间
  • 浏览器再次跟服务器请求这个资源时,在 requestheader 上加上 If-Modified-Since 字段,这个 header 字段的值就是上一次请求时返回的 Last-Modified 的值
  • 服务器再次收到资源请求时,根据浏览器传过来 If-Modified-Since 和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回 304 Not Modified ,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回 304 Not Modified 的响应时,response header 中不会再添加 Last-Modified的header ,因为既然资源没有变化,那么 Last-Modified 也就不会改变,这是服务器返回 304 时的 response header
  • 浏览器收到 304 的响应后,就会从缓存中加载资源
  • 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-ModifiedHeader 在重新加载的时候会被更新,下次请求时,If-Modified-Since 会启用上次返回的Last-Modified


Etag/If-None-Match

Etag实体标签, 服务器资源的唯一标识符, 浏览器可以根据ETag值缓存数据, 节省带宽. 如果资源已经改变, etag可以帮助防止同步更新资源的相互覆盖. ETag 优先级比 Last-Modified 高。这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变;其判断过程与 Last-Modified、If-Modified-Since 类似,与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。


怎么让浏览器不缓存静态资源?

实际上, 工作中很多场景都需要避免浏览器缓存, 除了浏览器隐私模式, 请求时想要禁用缓存, 还可以设置请求头: Cache-Control: no-cache, no-store, must-revalidate .


当然, 还有一种常用做法: 即给请求的资源增加一个版本号, 如下:

<link rel="stylesheet" type="text/css" href="../css/style.css?version=1.8.9"/>

这样做的好处就是你可以自由控制什么时候加载最新的资源.


不仅如此, HTML也可以禁用缓存, 即在页面的节点中加入标签, 代码如下:

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

上述虽能禁用缓存, 但只有部分浏览器支持, 而且由于代理不解析HTML文档, 故代理服务器也不支持这种方式.


总结:

ETag:文件可能很大,不可能去读取整个文件再用md5处理。一般用ctime(最后修改时间)+size(文件大小)

no-cache:代表不缓存过期的资源,每次发送请求静态资源时都需要向服务端进行一次过期认证,通常情况下,过期认真证需要配合(etag和Last-Modified)进行一个比较,如果验证并没有过期,则会发送304的状态码,通知浏览进复用浏览器的缓存。更确切的说,no-cache应该是do-not-serve-from-cache-without-revalidation1。

使用no-cache的目的就是为了防止从缓存中获取过期的资源。

而no-store才是真正的不进行缓存。


转载于:https://juejin.im/post/5b27bd536fb9a00e91043e95

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值