浏览器缓存总结

最近一直被浏览器的缓存行为所困扰,因此换了一番功夫做一次总结,话不多说直接进入正题。

浏览器的缓存策略包括两种:强缓存协商缓存

强缓存

强缓存即直接从本地读取缓存副本,不需要向服务器发起请求,这种方式是最快的。

HTTP 1.0   使用 Expires指定资源的失效时间,如expires:Fri, 14 Apr 2018 00:00:00 GMT。只要发送请求时间是在Expires之前,那么本地缓存始终有效,直接从本地缓存中读取数据,不去请求服务器。所以这种方式有一个明显的缺点,由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。

HTTP 1.1 使用Cache-Control(优先级高于Expires),主要的取值有以下几种:

  • max-age:它是一个相对时间,例如Cache-Control:max-age=3600,代表着资源的有效期是3600秒。

  • no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。

  • no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。

  • public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。

  • private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

协商缓存

协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。

HTTP 1.0 使用Last-Modify(服务端)/ If-Modify-Since(客户端)

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。

如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。这套缓存策略会存在以下几个问题:

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

  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);

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

HTTP 1.1 使用Etag(服务端)/ If-None-Match(客户端)

Etag/If-None-Match返回的是一个校验码。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。

与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。

以上内容可以总结为下图(来自于网络)

 

下面是我对强缓存Cache-Control的几种值的实验结果:

no-store

  • F5、地址栏回车时,html以及html内部的静态资源都会向服务器请求资源,状态码200
  • 前进回退时,html向服务器请求资源,但是html内部的其他静态资源会from cache

no-cache

  • F5、地址栏回车时,所有资源都会向服务器请求资源,状态码304,服务器只返回头部信息;如果修改了文件,服务器会重新生成这个资源的ETag,而浏览器请求时request headers里的还是上次服务器给的ETag,服务器会直接返回头部信息和消息主体;
  • 前进回退时,所有资源都是from cache。即使资源修改了,也是from cache

max-age=10 10秒钟过期

  •  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章