浏览器缓存的全过程:
200
,浏览器从服务器下载资源文件,并缓存资源文件与response header
,以供下次加载的时候对比使用200
时的时间差,如果没有cache-control
设置的max-age
,则没有过期,命中强缓存,直接从本地读取资源。如果浏览器不支持HTPP1.1
,则使用expires
头判断是否过期If-None-Match
和If-Modified-since
的请求Etag
的值判断被请求的文件又没有做修改,Etag
值一致则没有修改,命中协商缓存,返回304
;如果不一致则有改动,直接返回新的资源文件带上新的Etag
值并返回200
;Etag
值,则将If-Modified-Since
和被请求文件的最后修改时间做出比对,一致则命中协商缓存,返回304
;不一致则返回新的last-modified
和文件并返回200
很多网站的资源后面都加了版本号,这样做的目的是:每次升级了JS或者CSS文件后,为了防止浏览器进行缓存,强制改变版本号,客户端浏览器就会重新下载新的JS或CSS文件,以保证用户能及时获得网站的最新更新。
资源缓存的位置⼀共有 3 种,按优先级从⾼到低分别是:
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发送请求。
强缓存策略可以通过两种方式设置,分别是http头信息中的Expires属性
和Cache-Control
属性
(1) 服务器通过在响应头中添加Expires属性,来指定资源的过期时间。在过期时间以内,该资源可以被缓存使用,不必再向服务器发送请求。这个时间是一个绝对时间,它是服务器的时间,因此可能存在这样的问题,就是客户端的时间和服务端的时间不一致,或者用户可以对客户端的时间进行修改的情况,这样就可能会影响缓存命中的结果。
(2) Expires是http1.0中的方式,因为它的一些缺点,在HTTP1.1中提出一个新的头部属性就是Cache-Control属性,它提供了对资源的缓存的更精确的控制。
Cache- Control
可设置的字段
public
:设置了该字段值的资源表示可以被任何对象缓存。这个字段不常用,一般还是用max-age=来精确控制private
:设置了该字段的资源只能被用户浏览器缓存,不允许任何代理服务器缓存。在实际开发中,对于一些含用用户信息的HTML,通常都要设置这个字段值,避免代理服务器(CDN)缓存no-cache
:设置了该字段需要先和服务端确认返回的资源是否发生了变化,如果资源未发生变化,则直接使用缓存好的资源no-store
:设置了该字段表示禁止任何缓存,每次都会向服务端发起新的请求,拉取最新的资源max-age=
:设置缓存的最大有效期,单位为秒s-maxage=
:优先级高于max-age,仅适用于共享缓存(CDN),优先级高于max-age或者Expires头max-stale[=]
:设置了该字段表示客户端愿意接收已经过期的资源,但是不能超过给定的时间限制。一般只需要设置其中一种方式就可以实现强缓存策略,当两种方式一起使用时,Cache-Control
的优先级高于Expires
no-cache和no-store很容易混淆:
如果命中强制缓存,我们就无需发起新的请求,直接使用缓存内容,如果没有命中强制缓存,如果设置了协商缓存,这个时候协商缓存就会发挥作用了。
上面说到命中协商缓存有两个条件:
max-age=xxx
过期了no-cache
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生更改,则返回一个304状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
协商缓存也可以通过两种方式来设置,分别是http头信息中Etag
和Last-Modified
属性
(1) 服务器通过在响应头中添加Last-Modified属性来指出资源最后一次修改的时间,当浏览器下一次发送请求的时候,会在请求头中添加一个If-Modified-Since的属性,属性值为上一次资源返回时的Last-Modified的值。当请求发送到服务器后服务器会通过这个属性来和资源的最后一次的修改时间来进行比较,一次判断资源是否做了修改。如果资源没有修改,那么返回304状态,让客户端使用本的的缓存。如果资已经被修改了,则返回修改后的资源。
使用这种方法有一个缺点
,就是
Last-Modified
标注的最后修改时间只能精确到秒级,如果某些文件在1秒中以内,被修改多次的话,那么文件已经改变了,但是Last-Modified
却没有改变,这样会造成缓存命中的不准确。
(2) 因为Last-Modified
的这种可能发生的不准确性,http中提供了另外一种方式,那就是Etag
属性。服务器在返回资源的时候,头部添加了Etag
属性,这个属性时资源生成的唯一标识符,当资源发生改变的时候,这个值也会发生改变。在下一次资源请求的时候,浏览器会在请求头中添加一个If-None-Match
属性,这个属性的值就是上次返回的资源的Etag
值。服务器接收到请求后会根据这个值来和资源当前的Etag
值来进行比较,以此判断资源是否发生改变,是否需要返回资源。通过这种方式,比Last-Modified
的方式更加精确
当 Last-Modified
和 Etag
属性同时出现的时候,Etag
的优先级更⾼。使⽤协商缓存的时候,服务器
需要考虑负载平衡的问题,因此多个服务器上资源的 Last-Modified
应该保持⼀致,因为每个服务器上 Etag
的值都不⼀样,因此在考虑负载平衡时,最好不要设置 Etag
属性。
两种缓存策略在缓存命中时都会直接使用本地的缓存副本,区别只在于协商缓存会向服务器发送一次请求。它们缓存不命中时,都会向服务器发送请求来获取资源。在实际的缓存机制中,强缓存策略和协商缓存策略是一起合作使用的。浏览器首先会根据请求的信息判断,强缓存是否命中,如果命中则直接使用资源。如果不命中则根据头信息向服务器发起请求,使用协商缓存,如果协商缓存命中的话,则服务器不返回资源,浏览器直接使用本地资源的副本,如果协商缓存不命中,则服务器返回最新的资源给浏览器。
对于浏览器的缓存,主要针对的是前端的静态资源,最好的效果就是,在发起请求之后,拉取相应的静态资源,并保存在本地。如果服务器的静态资源没有更新,那么在下次请求的时候,就直接从本地读取即可,如果服务器的静态资源已经更新,那么我们再次请求的时候,就到服务器拉取新的资源,并保存在本地。这样就⼤⼤的减少了请求的次数,提⾼了⽹站的性能。这就要⽤到浏览器的缓存策略了。
所谓的浏览器缓存指的是浏览器将⽤户请求过的静态资源,存储到电脑本地磁盘中,当浏览器再次访问时,就可以直接从本地加载,不需要再去服务端请求了。
使用浏览器缓存有以下优点:
If-Modified-Since
、If-None-Match
、这就意味着服务器会对文件检查新鲜度,返回结果可能是304,也可能是200If-Modified-Since
、If-None-Match
,相当于之前从来没有请求过,返回结果是200