作为一个前端开发,你应该知道这些浏览器(http)缓存相关知识

506 阅读6分钟

前言

在熟悉浏览器缓存前,我们先啰嗦一下DNS以及CDN缓存。虽说这两者不属于浏览器缓存,但在一定程度上也会影响前端开发以及问题的定位,如果不适当了解一些,当出现问题的时候也会有点摸不着头脑。比如更新了服务端js文件,但是客户端死命的刷新,哪怕强制清除缓存后再刷新,文件内容还是没改变。这种问题大概率是中间商在作祟——CDN没更新。

DNS缓存

通过域名最终得到IP地址的过程叫做域名解析。有解析的地方就会存在缓存,从客户端的角度去看,大概可以分为四个范围,也是DNS查询的一个过程:

  • 1、浏览器查询自身的DNS缓存,如果查到,则解析结束直接返回域名对应的IP地址;
  • 2、从当前操作系统中查找,如果host文件中存在对应关系,则解析结束返回对应的IP地址;
  • 3、查找本地对应的DNS服务器,如果查找不到则继续;
  • 4、向根服务器发起请求,查找域名对应的IP地址关系。

以上情况大体了解即可,毕竟前端对DNS缓存几乎啥都不能做。

CDN缓存

什么是CDN?其实就是一个代理。比如一个跨国公司在中国开设业务,国内业务员每次汇报工作都要跟老外联系,这一来一回想必几天就过去了,效率如此之低。这个时候跨国公司如果在中国设立一个大中华区,每次汇报工作只要跟国内负责人联系即可。这个大中华区总裁就可以理解为代理,在国内业务员看来代理等同于老外。
其实简单的理解就是CDN相当于服务器的一个个拷贝,内容等同于根服务器上的内容,只是距离用户更近了,这样不仅可以节省网络请求的时间,还可以减轻根服务器的压力。这样的优势固然很好,但凡是都有两面性,有可能会产生服务端更新了文件但是CDN没有更新的情况,这样用户访问的时候仍然会访问过期的资源。

如何解决CDN更新问题?

  • 1、主动刷新。一般CDN运营商,都会提供一个后台,主动刷新文件内容。就是让中间服务器主动去根服务器拉取更新内容。
  • 2、修改query string值。比如更新一个图片,在图片URL地址后增加一个?v=123的参数,这个时候相当于中间服务器没有缓存,需要重新拉取根服务器图片。

缓存的加载顺序一般是先从内存中寻找,如果没有则从硬盘中寻找,再没有的话就从网络层面查找。

强缓存

不向服务器发送请求,每次都从本地缓存中加载资源文件。那么如何区分文件是从网路请求的还是本地的呢?从chrome浏览器开发者工具中的network栏目中可以看到如下图片,Size来源分三种情况:

  • 1、若显示类似12kB字样,则表示从网络上请求得到;
  • 2、若显示memory cache则表示从内存中得到;
  • 3、若显示disk cache则表示从磁盘缓存中加载的资源。

tool.png 那么什么情况下才会命中强缓存呢?在HTTP/1.1中,请求资源返回头(Response Headers)会有这么一个字段cache-control,假如值是max-age=600,则表示在这次请求后未来的10分钟内若再次请求该资源时,则无需从服务端加载,只要加载本地资源即可,这就算命中强缓存了。cache-control会有多个值,不同的值代表不同的意思:

  • 1、public表明相应可以被任何对象(客户端、CDN中间代理商等)缓存,即使是通常不可缓存的内容;
  • 2、private只有客户端(例如浏览器)才可以缓存(cache-control默认值);
  • 3、no-cache可以被缓存(注意不要被字面意思误解了),只是使用缓存的时候需要与服务端协商是否能够使用,后面“协商缓存”会讲到;
  • 4、no-store告诉浏览器不能缓存,每次都要从服务端拉取;
  • 5、max-age表示多少秒内缓存即将消失,是一个相对时间;
  • 6、s-maxage表示中间代理商缓存文件的有效期,例如cdn在这个时间之后需要重新拉取根服务器上的资源。

目前常见的也就上面6种情况,其他的暂不需要记忆,等需要的时候再查询也来得及。

有一点要特殊说明一下:http1时代的产物Expires字段会返回一个绝对时间,用于表示那个时间之前会命中强缓存,之后资源缓存将失效。但这种方法有很大的弊端,因为是绝对时间,当服务器时间与客户端时间相差较大的时候会产生混乱。且目前基本上不再使用,所以只要了解一下即可。

协商缓存

协商缓存就是当强缓存失效以后,浏览器携带一些标识再次向服务器发起请求,由服务器决定是继续使用缓存内容,还是重新拉取新资源。这里的一些标识主要是指这两对关键词:

  • 1、 ETagIf-None-Match
  • 2、 Last-ModifiedIf-Modified-Since

其中ETagLast-Modified是请求资源时返回的头信息之一,分别表示资源的唯一标识文件的最后修改时间。请求的资源发生变动的时候,这两个值都会修改。当没有命中强缓存的时候,浏览器会将这两个值分别以If-None-MatchIf-Modified-Since作为request请求头之一回传给服务器。服务器会先将收到的ETag值与当前文件ETag进行比对,若不同则表示浏览器缓存的文件过期,则会返回200状态码,同时将最新文件以及标识符返回给客户端。若ETag值相同则比对最后修改时间,若还是一致则表示文件没有更新,则返回304状态码表示文件未更新,缓存文件可继续使用。