浏览器缓存(二): 协商缓存

主流的浏览器缓存分为两类–强缓存和协商缓存,这里主要介绍的是协商缓存。

浏览器检查Web服务器生成的HTTP响应的标头,一般用于缓存的标题有四个:

  1. ETag
  2. CacheControl
  3. Expires
  4. LastModified

一、ETag

 

ETag是作为一个缓存验证令牌的字符串,这通常是文件内容的hash值。服务器可以在其响应中包括ETag,然后浏览器可以在请求中使用它(在文件过期之后),以便确定缓存是否包含过时的副本。如果hash相同,则资源未更改,服务器就以304状态码(未修改)来响应空主体,也就是说浏览器知道使用缓存副本仍然是可行的。不过要注意的是,ETag仅在文件从缓存过期时用于请求。

 

 

二、Cache-Control

 

所述Cache-Control头部具有一个数目,我们可以设置它的 Cache Behavior,Expiration 和 Validation,当然这些也可以组合在一起。

 

Cache Behavior如下:

1、Cache-Control: public

public表示资源可以被浏览器,CDN等缓存

2、Cache-Control: private

private表示资源只能由浏览器缓存

3、Cache-Control: no-store

这就告诉浏览器始终从服务器请求资源

4、Cache-Control: no-cache

 

 

这告诉浏览器缓存文件但不使用它,直到它检查服务器以验证我们有最新版本,主要使用ETag标头完成此验证。它通常与HTML文件一起使用,因为浏览器始终需要检查最新标记是有可用的。

 

三、Expires

 

1、Cache-Control: max-age=60

这指定了资源应该被缓存的时间长度(以秒为单位),也就是说它应该被缓存1分钟,建议最大值不应超过1年(max-age = 31536000)。

Cache-Control:s-max-age = 60

这仅适用于像CDN这样的中间缓存。

2、Validation (验证)

Cache-Control: must-revalidate

这表示必须在使用之前验证老旧的资源状态再缓存它,并且不应使用过期资源。

3、Expires(过期)

该过期头部信息是 HTTP 1.0,现在仍然在许多网站使用。此标头字段提供过期日期,在该日期之后就被视为无效了。

比如:Expires: Wed, 25 Jul 2018 21:00:00 GMT,如果Cache-Control中有max-age指令,浏览器将忽略此字段。

 

四、Last-Modified

 

这个标头也来自HTTP 1.0,比如:

Last-Modified: Mon, 12 Dec 2016 14:45:00 GMT

此字段说明上次修改资源的日期和时间。

 

HTTP缓存响应如下:

  1. AcceptRanges: bytes
  2. CacheControl: maxage=3600
  3. Connection: KeepAlive
  4. ContentLength: 4361
  5. ContentType: image/png
  6. Date: Tue, 25 Jul 2017 17:26:16 GMT
  7. ETag: “1109-554221c5c8540”
  8. Expires: Tue, 25 Jul 2017 18:26:16 GMT
  9. KeepAlive: timeout=5, max=93
  10. LastModified: Wed, 12 Jul 2017 17:26:05 GMT

 

信息解读:

服务器使用的是: Apache
第2行告诉我们max-age是1小时
第5行告诉我们这是一张PNG图片
第7行向我们表达了ETag值,该值将在1小时标记后用于验证,以验证资源是否未更改
第8行是Expires标题,因为设置了max-age,它将被忽略
第10行是Last-Modified标题,显示上次修改图片的时间

 

缓存的会出现的问题

通过以上,我们已经知道浏览器缓存是非常棒的,我们应该多多利用它。但我们也希望用户在进行更新时能够看到我们页面的最新版本,

我们不能指望他们每次访问我们的网站都得刷新,那不累死了,这类问题也是开发人员和用户经常遇到的。

比如用户可能在浏览器中缓存了一些旧的 JavaScript,导致表单重置,而不是在点击“登录”按钮时提交。

 

假设我们在名为app.min.js的JavaScript文件中修复了一个 bug,并更新推送到我们的网站。

比如HTML看起来像:

<script src=”assets/js/app.min.js”>

假如我们的Web服务器将JavaScript文件的max-age设置为1周(604,800秒)则:

Cache-Control: private, max-age=604800

 

更新后,一些用户反映他们仍然有问题bug。怎么回事呢?原来是第一个用户在2周前访问了该网站,并有一个缓存app.min.js的缓存副本。由于副本早于max-age,浏览器从服务器检索文件,并获得最新的版本。另一个用户在2天前就访问了该网站,并且还有一个缓存app.min.js的缓存副本,这个副本比 max-age 更新,所以他的浏览器仍然很可以使用缓存副本。遇到这样的情况,再客户端缓存资源的情况下,除了用户手动清缓存能够解决问题,开发者应该做些什么可以解决呢?1、对于脚本文件,每次更新更换版本号或文件名;2、服务端设置缓存过期时间比如开启etag,或者设置cache-control:max-age等等;3、刷新cdn缓存;

没有在响应头里设置缓存策略时,请求的响应头里是没有Cache-ControlExpires的,客户端会强缓存你的图片,而且会缓存很久;

比如有个图片不会经常变动,但更新了,希望xx时间后生效,所以我给这个图片的响应头加上Cache-Control: max-age=xxx就可以了,max-age以秒为单位,xxx即xxx

这样设置以后,用户第一次访问图片会被缓存,xxx秒内用户再次访问此图片,客户端不会发出网络请求,而是直接从磁盘缓存里读取。

xxx秒以后,缓存过期,用户再次访问此图片时,客户端就会发出请求从服务器获取最新图片。

 

图片是放在阿里云上的,应该如何设置响应头呢?

虽然图片是从CDN请求,但是我们CDN源站设置的是阿里云对象存储OSS的Bucket域名,对象存储OSS可以设置资源的HTTP响应头。

登录阿里云,进入对象存储OSS,找到资源所在Bucket-文件管理,进入资源所在目录,资源列表右边“更多”里有“设置HTTP头“,除了可以设置单个资源的HTTP头,还可以选择当页所有资源,批量设置HTTP头。

点击“设置HTTP头“,在“Cache-Control”字段填上值保存就可以了

发表评论

记录工作生活点滴。

返回
顶部