浏览器缓存浅析

前瞻

做前端开发有一个很头疼的事:缓存。缓存问题在移动端尤其严重,要想清缓存,不能像PC端使用强制刷新,需要手动清APP缓存等操作。对于缓存问题,我一直以来有点模棱两可,总想找时间好好梳理一下。

一者,前几天项目出了一个生产问题,关于版本控制,因为少加了一个随机数导致APP在IOS系统上登录后无法回调到模块页面。

二者,早上起床,看到微信订阅号推送一篇关于面试中遇到缓存问题被问倒的文章。

终于这两者促使我查阅并整理关于浏览器缓存问题的理解。

浏览器缓存

浏览器缓存的优点有:

  1. 减少冗余的数据传输,节省了流量
  2. 减少了服务器的负担,大大提升了网站的性能
  3. 加快了客户端加载网页的速度

浏览器缓存主要有两类:缓存协商和强制缓存

第一次访问服务器并且获取资源后,客户端会根据返回的信息来确定如何缓存资源,可能采用强缓存,也可能采用协商缓存,这都需要根据响应的header内容来决定的。

  1. 强缓存:不会向服务器发送请求,直接从缓存中读取资源,在控制台的network中可以看到该请求返回200的状态码,并且可以看到有些size是from disk,直接从本地获取。
  2. 协商缓存:向服务器发送请求,服务器会根据这个请求头中的参数(后续会详细讲解)来判断是否命中了协商缓存,如果命中了,则返回304状态码并带回新的参数通知浏览器从缓存中读取资源。

两个区别在于:都从客户端获取资源,强缓存不会发送请求,协商缓存会发请求。

强制缓存

浏览器在请求某资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息。

  1. exprires,这是http1.0时的规范;它的值是一个绝对时间GMT格式的时间字符串,也就是说告诉浏览器强缓存最终失效的时间点。如果在这个时间点前,都会从本地缓存中获取,否则就会发送请求到服务器获取新资源。
  2. cache-control:max-age=number ,这是http1.1时出现的规范;max-age的值是一个相对值,告诉浏览器一段时间内请求会命中强制缓存。cache-control除了该字段外,还有下面几个比较常用的设置值:
    1. no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
    2. no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
    3. public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
    4. private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

最佳实践:一般来说,图片、js、css等静态资源会添加强制缓存,并且给适当的过期时间,比如一个月。如果有版本更改,可以给文件名后添加随机数或者hash,当这个参数变化的时候,强缓存都会失效并重新加载。

注意:如果cache-control与expires同时存在的话,cache-control的优先级高于expires

扫描二维码关注公众号,回复: 633251 查看本文章

协商缓存

浏览器在请求某资源时,如果没有命中强制缓存,浏览器会发送请求到服务器,此请求会携带参数(If-Modified-Since和If-None-Match),这里的参数是根据第一次请求返回的有关缓存的header字段信息(Last-Modified和Etag)来匹配的。由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,浏览器会直接从缓存获取;否则返回新的响应header信息以及最新的资源内容。

  1. Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。

  2. If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定是否命中协商缓存;

ETag和Last-Modified的作用和用法,他们的区别:

1.Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;
2.在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值;
3.在优先级上,服务器校验优先考虑Etag。

缓存过程

  • 浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存。

  • 下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modified-Since的请求。

  • 服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200。
  • 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200。

网上流传的关于浏览器缓存的两幅图如下:

浏览器第一次请求时:

img

浏览器后续再进行请求时:

img

参考文档

1. 浏览器缓存机制浅析

2. 浏览器的协商缓存与强缓存

3. http协商缓存VS强缓存

猜你喜欢

转载自blog.csdn.net/qq_33388137/article/details/79524494
今日推荐