浏览器缓存分为强缓存和协商缓存
强缓存
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发起请求。强缓存策略可以通过 http 头信息中的 Expires 属性和 Cache-Control 属性两种方式设置命中后返回 200。
Cache-Control设置的public、private和max-age未过期的情况都属于强缓存
协商缓存
和服务器沟通,是否使用缓存
有两种情况
Cache-Control的值为max-age过期了
Cache-Control的值为no-cache
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
Cache-Control的具体字段
HTTP 1.1版本的响应头
一个
max-age用于指定缓存时间,单位为秒public:指示服务器资源是公开的。比如有一个页面资源,所有人看到的都是一样的。这个值对于浏览器而言没有什么意义,但可能在某些场景可能有用。本着「我告知,你随意」的原则,HTTP协议中很多时候都是客户端或服务器告诉另一端详细的信息,至于另一端用不用,完全看它自己。private:指示服务器资源是私有的。比如有一个页面资源,每个用户看到的都不一样。这个值对于浏览器而言没有什么意义,但可能在某些场景可能有用。本着「我告知,你随意」的原则,HTTP协议中很多时候都是客户端或服务器告诉另一端详细的信息,至于另一端用不用,完全看它自己。no-cache:告知客户端,你可以缓存这个资源,但是不要****直接****使用它。当你缓存之后,后续的每一次请求都需要附带缓存指令,让服务器告诉你这个资源有没有过期。no-store:告知客户端,不要对这个资源做任何的缓存,之后的每一次请求都按照正常的普通请求进行。若设置了这个值,浏览器将不会对该资源做出任何的缓存处理。s-maxage:优先级高于max-age,仅适用于共享缓存(CDN),优先级高于max-age或者Expires头;max-stale:设置了该字段表明客户端愿意接收已经过期的资源,但是不能超过给定的时间限制。
Cache-Control还可以设置以上一个或多个值:
比如,Cache-Control: public, max-age=3600表示这是一个公开资源,请缓存1个小时。
Expires
HTTP 1.0版本的响应头
在HTTP1.0版本中,是通过Expire响应头来指定过期时间点的,例如:
Expire: Thu, 30 Apr 2020 23:38:38 GMT服务器通过在响应头中添加 Expires 属性,来指定资源的过期时间。在过期时间以内,该资源可以被缓存使用,不必再向服务器发送请求。这个时间是一个绝对时间,它是服务器的时间,因此可能存在这样的问题,就是客户端的时间和服务器端的时间不一致,或者用户可以对客户端时间进行修改的情况,这样就可能会影响缓存命中的结果。
如果Expires和Cache-Control的两个字段同时存在,Cache-Control的优先级更高
Last-Modified/If-Modifed-Since
服务器通过在响应头中添加 Last-Modified 属性来指出资源最后一次修改的时间,当浏览器下一次发起请求时,会在请求头中添加一个 If-Modified-Since 的属性,属性值为上一次资源返回时的 Last-Modified 的值。
当请求发送到服务器后服务器会通过这个属性来和资源的最后一次的修改时间来进行比较,以此来判断资源是否做了修改。如果资源没有修改,那么返回 304 状态,让客户端使用本地的缓存。如果资源已经被修改了,则返回修改后的资源。使用这种方法有一个缺点,就是 Last-Modified 标注的最后修改时间只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,那么文件已将改变了但是 Last-Modified 却没有改变,这样会造成缓存命中的不准确。
ETag/if-None-Match
因为 Last-Modified 的这种可能发生的不准确性,http 中提供了另外一种方式,那就是 Etag 属性。服务器在返回资源的时候,在头信息中添加了 Etag 属性,这个属性是资源生成的唯一标识符,当资源发生改变的时候,这个值也会发生改变。在下一次资源请求时,浏览器会在请求头中添加一个 If-None-Match 属性,这个属性的值就是上次返回的资源的 Etag 的值。服务接收到请求后会根据这个值来和资源当前的 Etag 的值来进行比较,以此来判断资源是否发生改变,是否需要返回资源。通过这种方式,比 Last-Modified 的方式更加精确。低于一秒更精确。**当 Last-Modified 和 Etag 属性同时出现的时候,Etag 的优先级更高。**使用协商缓存的时候,服务器需要考虑负载平衡的问题,因此多个服务器上资源的 Last-Modified 应该保持一致,因为每个服务器上 Etag 的值都不一样,因此在考虑负载平衡时,最好不要设置 Etag 属性。