本文讨论的是浏览器对静态文件的缓存,由于通常一个web站点占用最大带宽的通常是静态信息,例如js,css,img。因此了解浏览器对静态资源的缓存情况是优化站点提高访问速度的关键,其实也是最简单有效的。

    以下基于3个问题来讨论 :

  1.     为什么要缓存
  2.     什么情况下浏览器会缓存
  3.     谁来控制缓存

    第一个问题:

    目前来说通常一个Web网站最大的流量来源于静态图片文件,使用缓存后可以减少同一客户端对同一静态资源的重复下载。

    首先要说的是缓存并不是说浏览器缓存后的信息再次访问浏览器就不会和服务端产生通信(它需要和服务端确认一下它缓存的东西是不是最新的,如果是则使用不是的话重新下载),因此浏览器缓存后并不会将少与服务器的交互次数,也就是说并不能使浏览器与服务端交互次数降低,但是会降低与服务端的连接时长,变相地减少了服务端的并发。

    因此浏览器缓存对于服务端来说节省了带宽,对于客户端来说减少了重复下载同一资源的次数,也就加快了访问速度。

    第二个问题:

    解释第一个问题时提到浏览器缓存某一信息后再次访问时需要基于某一标识来确认一下它缓存的东西是否是最新的。这个标识有两种:

  • Last_modified

             当浏览器请求一个静态资源,服务端返回该资源时会在返回的Http头部加入一条Last_modified的信息,该信息代表该资源最后一次修改的时间。浏览器再次请求该资源时会在http请求头部加入if-modified-since的信息,该信息为浏览器缓存的内容的最后修改时间。(以上说法基于服务端开启Last-modified的功能,并且开启响应if-modified-since的功能。)

  • E-tag

             功能类似last_modified,e-tag是对于一个资源的标识。浏览器通过if-none-match来向服务端咨询资源是否为最新的。E-tag与Last_modified不同之处在于如果存在周期性更改但文件内容不会变更的情况下使浏览器能够成功缓存。(不过暂时我没有接触过这种情况)

    综上,服务端只有在提供了确认某一资源是否为最新的标识,并且能够响应浏览器的询问才能够缓存。

    第三个问题:

    浏览器的种类及版本繁多,对于缓存的机制设置也不一样。

    对于last_modified作为标识在解释第二个问题时我默认浏览器总是对于访问过的内容进行缓存,而实际上浏览器会根据Last_modified来计算一个过期时间,在这个时间内浏览器才会发送if-modified-since,计算方法各浏览器并不一样。对于这些机制很难全部把握,并且在实际生成环境中我们更希望能够控制这个时间,这个也是在用Yslow做网站分析时提示尽量这么处理。

     服务端控制的方式有在httpd头部加入expires或cache_control来控制。expires指出了该文件的过期时间,cache_control用max-age指令指定该资源被缓存多久

     例如服务端用nginx来做web服务器,希望控制缓存css文件30天。

    


  
  1. location ~* \.css$ { 
  2.             expires 30d; 
  3.         } 

     Nginx的expires会在响应http头部同时加上expires和计算出的cache_control。

    对于E-tag来说本身就是服务端控制的。