前端缓存之HTTP缓存(二)

1.1 什么是HTTP缓存?

HTTP缓存:当客户端向服务端请求资源时,会先去到浏览器缓存,如果浏览器缓存有需要请求资源的副本,就可以直接从浏览器缓存中提取,而不会去到服务器。

常见的http缓存都只能缓存get方式请求响应的资源,不能处理其他类型的响应。

HTTP缓存都是从第二次请求开始的,当第一次请求资源时,服务器会返回资源,并在请求头中传回资源的缓存参数;第二次请求时,浏览器会对这些参数进行判断,命中强缓存的就返回200,不命中会把请求参数加到请求头中传给服务器,判断是否命中协商缓存,命中协商缓存返回304(简单点来说就是服务端已经执行了GET,但文件未发生变化),否则服务器会返回新的资源。

而HTTP缓存分为强缓存和协商缓存。强缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。

1.1.1 强缓存

强缓存在缓存数据未失效的情况下(即Cache-Control的max-age没有过期或者Expires的缓存时间没有过期),那么就会直接使用浏览器的缓存数据,不会再向服务器发送任何请求。强制缓存生效时,http状态码为200。这个方式页面加载的速度很快,性能好,但是在这期间,如果服务端的资源修改了,页面上是无法获取的,因为它不会再向服务器发送请求了。就好比如我们在实际开发中,修改了某个页面的样式,在页面上刷新但修改的内容没有生效,因为使用的是强缓存,这时候就需要Ctrl+F5。

header属性:

  • Pragma(HTTP/1.0)

    • no-cache:不直接使用缓存,根据新鲜度来使用缓存,

      响应头不支持这个属性,优先级最高,但在HTTP/1.1废弃了

  • Cache-Control(HTTP/1.1)

    • no-cache:不直接使用缓存,根据新鲜度来使用缓存

    • no-store:不使用缓存,每次都是请求下载新资源

    • max-age:缓存时长

    • public/private:是否只能被单个用户使用,默认为private

    • must-revalidate:每次访问需要缓存校验

      请求头和响应头都支持这个属性,不适用于HTTP/1.0,在缓存未失效前,得不到修改后的资源

  • Expires(时间)

    • GMT时间

      服务端和客户端的时间不一致会出现问题,适用于HTTP/1.0和HTTP/1.1,在缓存未失效前,得不到修改后的资源

1.1.2 协商缓存

当第一次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过期,也或者他的属性设置为no-cache(不走强缓存),那么浏览器第二次请求时就会与服务器进行协商,与服务器对比判断资源是否进行了更新。如果服务器端的资源没有修改,那么就会返回304,告诉浏览器可以使用缓存中的数据,这样就减少了服务器的传输压力。如果数据有更新服务器就会返回200状态码,服务器就会返回更新后的资源并且将缓存信息一起返回。

  • ETag/If-Not-Match(HTTP/1.1)

    • 校验值

      默认使用hash算法,在分布式环境下可能会出现不同服务器生成的ETag值不一致;精确的判断资源有无被修改,可识别一秒内的修改次数;计算ETag需要性能消耗

  • Last-Modified/If-Modified-Since(HTTP/1.0)

    • GMT时间

      只要资源修改,无论内容有无变化,都会将资源返回客户端;以时刻为标识,无法获取一秒内的修改变化;某些服务器不能准确获取最后的修改时间

当浏览器第一次向服务器发送请求时,会在响应头中返回协商缓存头的属性:ETag和Last-Modified,其中ETag返回的是一个hash值,Last-Modified返回的是GMT格式的最后修改时间。浏览器第二次发送请求时,会在请求头中带上与ETag对应的If-Not-Match,这个值就是响应头中返回的ETag的值,Last-Modified对应If-Modified-Since。服务器在接收到这两个参数后会进行比较,如果返回304,则说明请求资源没被修改,浏览器可以直接在缓存中获取数据,否则服务器会直接返回数据。

ETag/If-Not-Match是在HTTP/1.1出现的,主要是解决以下问题:

(1)、Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间

(2)、如果某些文件被修改了,但是内容并没有任何变化,而Last-Modified却改变了,导致文件没法使用缓存

(3)、有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

2.1 如何使用HTTP缓存?

一般需要缓存的资源有html页面和其他静态资源:

  • html

    html页面缓存设置主要是在head标签中嵌入meta标签,这种方式只对页面有效,对页面上的资源无效

    • 禁用缓存

      • IE浏览器才识别的标签,不一定会在请求字段加上Pragma,但的确会让当前页面每次都发新请求

        <meta http-equiv="pragma" content="no-cache">
        
      • 其他主流浏览器识别的标签

        <meta http-equiv="cache-control" content="no-cache">
        
      • IE浏览器才识别的标签,该方式仅仅作为知会IE缓存时间的标记,你并不能在请求或响应报文中找到Expires字段

        <meta http-equiv="expires" content="0">
        
    • 设置缓存

      • 仅有IE浏览器才识别的标签

        <meta http-equiv="Expires" content="Mon, 20 Aug 2018 23:00:00 GMT" />
        
      • 其他主流浏览器识别的标签

        <meta http-equiv="Cache-Control" content="max-age=7200" />
        
  • 静态资源

    静态资源的缓存一般是在web服务器上配置,例如nginx,Apache。

2.2 注意点

  1. 强缓存情况下,只要缓存还没过期,就会直接从缓存中取数据,就算服务器端有数据变化,也不会从服务器端获取了,这样就无法获取到修改后的数据。决解的办法有:在修改后的资源加上随机数,确保不会从缓存中取。

  2. 尽量减少304的请求,因为我们知道,协商缓存每次都会与后台服务器进行交互,所以性能上不是很好。从性能上来看尽量多使用强缓存。

更多详细的内容可以看看这位大佬写的文章

你可能感兴趣的:(面试)