前端缓存

什么是前端缓存?

浏览器将对于已经请求过的资源缓存起来,等到下一次请求同样资源时,浏览器直接将缓存副本返回响应,不必向浏览器发送请求

前端缓存的好处

  • 缩短网络请求的距离,减少延迟,加快网页打开速度,性能优化
  • 资源重复利用,减少带宽,降低服务器压力

如何实现前端缓存?

首先来了解与缓存有关的HTTP报文字段

  • 通用首部字段

    • Pragma

      • 定义在Meta标签,通常指为no-cache,禁用缓存

        1
        <meta http-equiv="Pragma" content="no-cache">
        • 浏览器设置作用不大,服务器端设置为主
        • 仅IE能识别
        • 与禁用缓存相对的是启用缓存,Expires出现了
    • Cache-Control

      • 解决服务器和浏览器时间标准不一致
      • 定义缓存过期时间,与Pragma Expires相比,优先级最高
        • 如果资源缓存过期,但资源还是一样,在资源较大的情况下,是不应该又去服务器请求一遍的
        • 我们需要让服务器知道前端缓存的资源是否跟自己一致,如果一致就让浏览器直接用缓存,这时候Last-Modified出现了
  • 请求首部字段
    • If-Match
      • 浏览器通过PUT方法时,通过这个字段传递ETag
    • If-None-Match
      • 浏览器告诉服务器如果ETag没匹配上,返回新资源,否则返回304
        • ETag就存储在这个字段中
    • If-Modified-Since
      • 浏览器通过这个字段告诉服务器如果最后修改时间一致,则返回304
        • Last-Modified就存储在这个字段中
    • If-Unmodified-Since
      • 浏览器通过这个字段告诉服务器如果最后修改时间不一致,则返回412
  • 响应首部字段
    • ETag
      • 服务器返回资源的同时,将ETag一并返回,浏览器接收到后为资源打上这个标记,下一次请求时,将这个值发给服务器,服务器和之前的作对比,如果一致,返回304;否则返回新资源
      • 通过对资源进行某个算法,生成一个类似md5的唯一标识符,而不仅仅靠修改时间
        • 如果和Last-Modified同时使用,需要两者都返回304,才会走缓存,否则返回新资源
  • 实体首部字段

    • Expires

      • 服务器返回的资源缓存过期时间(GMT 格林尼治时间),时间点是服务器的时间

        • 在浏览器,IE下可以这样设置,这种做法也仅限IE

          1
          <meta http-equiv="expires" content="mon, 18 apr 2016 14:30:00 GMT">
        • 得在服务器端报头返回该字段,缓存过期时间才能正确生效

        • 同时设置,Pragma优先级更高
        • 但如果服务器和浏览器的时间标准不一致,这个设置也就失效了,因此Cache-Control出现了
    • Last-Modified
      • 服务器端资源的最后修改时间
      • 服务器向浏览器返回资源的同时,会携带一个Last-Modified,它的值为格林尼治时间;浏览器接收到响应后,会给资源标记上这个值,等到下一次向服务器请求时,将这个值一并发过去,服务器就会对比浏览器发过来的值和之前发给浏览器的值,如果两个最后修改的时间一致,则返回304,让浏览器直接读取缓存资源
        • 不足:当服务器资源被修改,但实际内容没变,这个时候还是会将资源返回,这时候ETag出现了

强缓存不会发送请求到服务器,协商缓存会发送请求到服务器,通过请求首部字段验证

强缓存:Pragma / Expires / Cache-Control

协商缓存:Last-Modified/If-Modified-Since、ETag/If-None-Match

If-Modified-Since/Last-Modified

If-Modified-Since存在于请求头中,当它被发送到服务器时,服务器会将它和Last-Modified的值作对比,如果两者日期一致,则告知浏览器可以使用本地缓存

If-None-Match/Etag

If-None-Match存储一个字符串,当它被发送到服务器时,服务器会将它和Etag的值作对比,如果匹配上了,则告知浏览器可以使用本地缓存

流程是这样的:浏览器第一次请求页面,服务器在返回结果的同时,也将Last-Modified和Etag值传递过去;浏览器接收到响应,将这两个值都缓存起来;等到下一次请求同个页面,这两个值会将这两个值分别放入If-Modified-Since/If-None-Match并发送到服务器,服务器拿这两个值和之前的作对比,如果其中一个命中,就返回304和空响应体,这就是协商缓存的过程

具体应用

  • 使用Expires来兼容旧浏览器
  • 使用Cache-Control来精准控制缓存
  • 使用ETag和Last-Modified来进一步复用
  • 一般缓存时间为60s
  • 对于静态资源(如图片)则会久一点
    • 浏览器可以在图片的URL后设置max-age
    • 浏览器可以对静态资源以版本形式发布,加上hash值,以确保能及时从服务器获取最新资源