说说浏览器缓存是前端面试中常常会被面试官提及的问题,要回答好,就要全面理解浏览器的缓存机制,这样不仅可以在面试时加分,在日后的工作中也能写出更符合业务逻辑、更高效的代码。
缓存,就是将网页相关数据,比如静态的图片、css文件、js文件等暂时存放在浏览器的内置数据库中。因为这类文件一般是不会有大的变动的,所以,在满足某些条件的时候就可以从这里取出,而无需每次都向服务器索要,也无需每次都需要服务器发送一遍。这样就达到了减少网络请求、提高页面加载速度的目的,提升了用户体验,因此这也是一个很好的前端优化方案。
浏览器缓存分为强制缓存和协商缓存。
强制缓存
强制缓存发生在浏览器,就是浏览器自己判断是否需要从缓存中取出资源,这个过程有以下几个步骤:
-
- 浏览器发出请求时,会先查看自己是不是缓存了该资源。
-
- 如果没有缓存资源,就将请求发送给服务器,服务器处理后,返回资源及状态码200,并且响应头(header)包含两个字段Expires和Cache-control,Cache-control中又包含max-age,这就表示,服务器要求浏览器缓存该资源。浏览器收到资源后,将这两个字段和资源都缓存起来。
-
- 如果有缓存资源,就会先判断max-age,它表示资源的有效期,比如max-age=3600s,就表示自上次获取该资源后1小时内有效。
- 3.1 如果未超出max-age,则从缓存中取出该资源并返回,且状态码为200。
- 3.2 如果超出,则继续判断Expires,它表示资源的具体过期时间。
- 3.2.1 如果当前客户端时间没有超过Expires,就表明缓存有效,直接取出资源即可。
- 3.2.1 如果当前客户端时间超过Expires,就表明缓存过期,那么就向服务器发起请求。服务器处理后,依然返回资源和带有新的Expires和Cache-control的响应头。
Expires和Cache-control都是后台开发人员指定并返回的,其中前者是http1.0的产物,后者是http1.1的产物。
Expires指定了一个具体的过期时间,这个时间并不可靠,因为Expires保存的是服务器的时间,而如果客户端的时间被用户修改了,那么就不能作为参考了。这样就会造成要么服务器的数据早就修改了,但缓存还未过期,那么用户永远不能及时拿到最新数据;要么就是刚缓存就会即刻失效。
cache-control它可以包含多个字段其中max-age的值是一个数字,单位是秒,表示多少秒之后这个缓存过期。它是一个相对时间,参照的是浏览器接收到资源的时间。它的优先级要高于Expires,因为它更可靠。
协商缓存
协商缓存发生在服务器,就是服务器去判断是否需要返回资源。这个过程有以下几个步骤:
-
- 首次访问资源时,服务器返回资源并且响应头带有ETag和Last-Modified两个字段,前者是一个映射token,表示资源在服务器中的信息,后者这是资源的最后修改日期时间戳。
-
- 再次访问资源时,请求头会带有If-None-match和If-Modified-Since两个字段,它们的值分别是ETag和Last-Modified的值。然后服务器会根据这两个字段来判断在客户端的缓存是否有效。
-
- 如果缓存有效,则服务器返回304状态码,并且不会返回响应实体。客户端收到后,就会从缓存取出资源。
-
- 如果缓存无效,则服务器就将请求的资源返回,并带上新的ETag和Last-Modified。
强制缓存+协商缓存
实际工作中很可能会出现强缓和协商缓并存的情况,那么这个时候浏览器和服务器又是如何进行处理的呢?一张图给出答案。
图中表示,第一次请求资源时,浏览器中无相关缓存,服务器直接返回资源,响应头含强制缓存和协商缓存的决定性字段。当浏览器再次请求时,会先判断强制缓存,若强制缓存命中(有效),则直接使用缓存,否则发送请求由服务器判断协商缓存,若命中,取缓存,否则返回资源和新的响应头。