在工作中,前端必不可少的是把静态资源放到静态服务器上,这个时候就必须做一些配置,用来优化以及减少服务器压力,gzip和缓存就是必不可少的,这直接影响到客户的体验,一个良好的缓存配置有以下的优点:

  • 减少了不必要的数据传输,节省带宽
  • 减少服务器负担,提升网站性能
  • 加快客户端加载网页的速度
  • 用户体验友好

但也有相应的缺点:

  • 资源如果有更改但是客户端不及时更新会造成用户获取信息滞后,如果老版本有bug的话,情况会更加糟糕。

所以,为了避免设置缓存错误,掌握缓存的原理对于我们工作中去更加合理的配置缓存是非常重要的。

强缓存

什么是强缓存呢?强就是强制的意思,强制缓存,一般都是由服务器响应的 cache-controlexpires控制,可以设置缓存的时间,缓存的类型

Expires

Expires是http1.0的规范,它的值是一个绝对时间的GMT格式的时间字符串。比如网页的 Expires值是:

expires:Mar, 06 Apr 2020 10:47:02 GMT。

这个资源代表资源的失效时间,只要发送请求时间是在 Expires之前,那么本地缓存始终有效,则在缓存中读取数据。所以这种方式有一个明显的缺点,由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱

Cache-Control

http1.1中出现的,一般利用该字段的max-age来判断,这个值是一个相 对时间。例如:

Cache-Control:max-age=3600 // 代表着资源的有效期是3600秒

除了该字段还有其他的几个常用的值。

| 类型 | 描述 |
| - | - |
| no-cache | 不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。 |
| no-store | 直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。 |
| public | 可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。 |
| private | 只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。 |

Cache-Control与Expires的优先级

Cache-Control与Expires可以在服务端配置同时启用,同时启用的时候Cache-Control优先级高。比如:

cache-control:max-age=691200
expires:Fri, 06 Mar 2020 10:47:02 GMT

那么表示资源可以被缓存的最长时间为691200秒,会优先考虑 max-age

ngxin启用强缓存

  1. 通过设置nginxexpires进行缓存,下面表示缓存12秒,12秒之后浏览器优请求服务器资源
location ~ .*\.(js|css)?$
    {
        expires      12s;
    }
  1. 直接添加header,本质上上面的那个也是添加header,具体参数为文档
  location ~* ^.+\.(css|js|txt|xml|png|jpg|gif|jpeg|webp)$ {
        add_header Cache-Control no-store;
        add_header Cache-Control max-age=3600;
        add_header Cache-Control public;
        add_header Cache-Control only-if-cached;
        add_header Cache-Control no-cache;
        add_header Cache-Control must-revalidate;
  }

结果:

image.png

image.png

可以看到浏览器请求的js文件如果是在12s内刷新多次,那么就会直接取缓存中的文件,那么你还可能注意到12s之后返回的是304,这个时候表示的资源没有变化,这属于协商缓存。

协商缓存

协商缓存是由服务器确定缓存资源是否可用。主要涉及到两组header字段:

EtagIf-None-Match

Last-ModifiedIf-Modified-Since

Last-Modify/If-Modify-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。

Etag/If-None-Match

从上面看可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?

首先,Etag/If-None-Match 是“实体标签”(Entity Tag)的缩写,是资源的一个唯一标识,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。

因此,Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
  • 某些服务器不能精确的得到文件的最后修改时间。

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

nginx开启协商缓存

响应头里有Cache-Control: no-cache,表示使用协商缓存

location /picture/ { 
  add_header Cache-Control no-cache;
  alias D:/luozixi/tcp_test/picture/; 
}

浏览器刷新问题

当你点“刷新”按钮的时候,浏览器会在请求头里加一个“Cache-Control: maxage=0”。因为 max-age 是“生存时间”,而本地缓存里的数据至少保存了几秒钟,所以浏览器就不会使用缓存,而是向服务器发请求。服务器看到 max-age=0,也就会用一个最新生成的报文回应浏览器。

Ctrl+F5 的“强制刷新”又是什么样的呢?

它其实是发了一个“Cache-Control: no-cache”,含义和“max-age=0”基本一样,就看后台的服务器怎么理解,通常两者的效果是相同的。

参考链接:[
HTTP强缓存和协商缓存 - JavaScript学习笔记 - SegmentFault 思否segmentfault.com](https://link.zhihu.com/?target=https%3A//segmentfault.com/a/1190000008956069)

大公司里怎样开发和部署前端代码?www.zhihu.com

缓存策略:强缓存&协商缓存

最后修改:2021 年 06 月 07 日 12 : 29 PM
如果觉得我的文章对你有用,请随意赞赏