Wedcache

浅谈前端缓存机制

在做前端优化,特别是提升网页加载速度的时候,缓存无疑是一个很有效的方法。
但是涉及到缓存的知识多而杂,为了更好的自我总结,查阅了网上很多的资料,在此写下一些对前端缓存机制的理解


所以我们日常前端开发中涉及到的缓存有哪几种?

一. CDN缓存

CDN是什么东西?

CDN(Content Delivery network,内容分发网络),用户在进行CDN进行数据请求的时候,CDN会自动的选择一个距离用户最近的节点来做出响应。有了CDN之后,客户端在与服务端的交互过程中间加入了CDN这个角色,他作为一个边缘节点可以帮助源点服务端预先对用户的请求进行处理,分析缓存是否过期,再选择是否向源站发起请求,请求数据。

优势在于?

  • CDN节点解决了跨地域和跨运营商的问题,大大降低了数据传输的延时性。
  • 因为大部分的请求都在边缘的节点完成,起到了分流的作用,所以大大减轻了源站的压力。


二. DNS缓存

DNS是个什么东西?

首先DNS是指将域名URL转化为服务器的主机IP,在DNS查询解析的过程中,浏览器什么都做不了,保持空白的页面,所以提升DNS的查询速度也是前端的优化之一。

DNS缓存就是优化方式之一,对DNS进行缓存可以减少重复的查找,提升网页的打开速度,但是缓存时间过长,也会容易造成访问的正确率下降,没办法及时检测到服务器的IP变化。

(当然对DNS进行优化并不止缓存这一种方式,DNS预解析也是一种很好的方式,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。)



三. 客户端缓存(强缓存和协商缓存)

客户端缓存是个什么东西?

客户端缓存是 缓存的最后一层,是直接面对客户端的客户端缓存。通常也把这部分称为web缓存。web缓存位于客户端。缓存会根据进来的请求保存输出内容的复本,例如html页面、图片文件等,然后,当下一个请求来到时,如果是相同的URL,缓存直接使用复本相应请求访问,而不是向源服务器再次发送请求。

缓存策略如下

  1. 浏览器发起资源请求

  2. 首先通过请求头信息判断是否击中强缓存

  3. 判断方式{标识为Expires(HTTP/1.0)或Cache-Control(HTTP/1.1),如果Expires和Cache-Control同时使用的话,后者的优先级较高}

    ​ a、不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)。

    ​ b、存在该缓存结果和缓存标识,但该结果已失效,强制缓存失败,则使用协商缓存。

    ​ c、存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果。(没有向服务器发起请求,浏览器直接返回200,并直接从本地缓存中读取资源)

  4. 当缓存标识存在且过期的时候,便需要使用协商缓存,如果存在Etag,则校验If-None-Match,
    如果存在Last-Modified,则校验,If-Modified-Since,
    ​如果一致,服务器返回304,浏览器直接从缓存中读取资源,若未命中缓存,服务器返回资源,并对Etag和Last-Modified进行更新。






Q1:为什么last-modified还要有etags?*

1、last-modified的时间只能精确到秒,如果资源修改得比较频繁,频率在秒以下时,就出现了偏差。

2、当存在周期性重写某些资源,但资源实际内容并未发生改变,或修改的内容并不重要如注释等,就应当使用Etag。

Q2:Etag的缺点?

ETag本身需要消耗 CPU,而它的优先级比 Last-Modified 高,当它存在时服务器无论 Last-Modified 是否存在都会使用它判断,ETag在分布式系统中生成的值可能不一样,会导致缓存失效

Q3:强缓存和协商缓存的区别?

强缓存:客户端第一次问服务器要某个资源时,服务器丢还给客户端所请求的这个资源同时, 告 诉客户端将这个资源保存在本地,并且在未来的某个时点之前如果还需要这个资源,直接从本地获 取就行了, 不用向服务器请求。这种方式缓存下来的资源称为强缓存。

协商缓存:客户端第一次问服务器要某个资源时,服务器丢还给客户端所请求的这个资源同时,将该资源的一些信息也返回给客户端,告诉客户端将这个资源缓存在本地。当客户端下一次需要这个资源时,将请求以及相关信息一并发送给服务器,由服务器来判断客户端缓存的资源是否需要更新:如不需要更新,就直接告诉客户端获取本地缓存资源(304); 如需要更新,则将最新的资源连同相应的信息一并返回给客户端。

Q4:服务端资源更新时,怎么强制更新客户端缓存?
显然,代码更新到线上的时候,用户浏览器是不能自行更新的,我们不可能做到每次服务端更新的时候强行让用户清理一次缓存。
所以应该怎么做到让服务端及时的更新客户端的缓存呢?
在资源请求的URL中增加一个参数,比如:js/mian.js?ver=0.7.1。这个参数是一个版本号,每一次部署的时候变更一下,当这个参数变化的时候,强缓存都会失效并重新加载。这样一来,静态资源,部署以后就需要重新加载。这样就比较完美的解决了问题。


参考文章: