前端缓存知识介绍

35 阅读5分钟

前端缓存知识介绍

缓存分为强缓存和协商缓存;

缓存的好处有很多,比如:减轻服务器的压力、快速响应、减轻网络压力、为用户节省流量等

缓存有时候也会有一些问题:比如:客户端不能获取到最新的资源,导致部署升级失败,但是现在这个已经不是问题,通过打包构建工具可以解决,文章最后会有对应的解决原理解析。

强缓存

强缓存使用ExpiresCache-Control两个响应头字段,同时存在时Cache-Control的优先级更高。

命中强缓存时,客户端不会去服务器请求资源,而是直接从缓存中读取内容,返回HTTP状态码200

Expires 出现在响应头中,代表该资源的过期时间,是一个GMT格式的标准时间

客户端第一次请求服务端的时候,服务端会返回资源和响应头 Expires,表示资源的具体过期时间。 如果在过期时间内,客户端又去请求该资源,则命中缓存,直接使用缓存中的,不去请求服务端了。

Expires 需要优化地方

  • 缓存时间过期以后,不管资源有没有更新都固定去服务端请求一次,不灵活。
  • 缓存过期时间是一个具体的时间,这个时间依赖于客户端的时间,如果不准确或者被人为改动,会影响缓存命中。

Cache-Control 出现在请求/响应头中,通过不同的属性控制不同的缓存策略

响应头的属性有

  • max-age:在多少秒内有效,是一个相对时间
  • s-maxage:在缓存服务器上缓存的有效时间,只对 public 有效
  • no-cache:不使用本地缓存,需使用协商缓存
  • no-store:不使用缓存,每次都会重新从服务端下载资源
  • public:可以被客户端/中间代理服务器缓存
  • private:可以被客户端缓存,不可以被中间代理服务器缓存,默认值

请求头的属性有

  • max-stale: 5 表示客户端获取代理服务器缓存时,超过过期时间5秒之内都是可以的
  • min-fresh: 5 表示客户端获取代理服务器缓存时,需要在过期时间5秒之前才行
  • only-if-cached 表示只获取代理服务器缓存,代理服务器缓存过期则返回504报错

协商缓存

协商缓存主要有两组四个头字段,两两配合使用,If-Modified-SinceLast-ModifiedEtagIf-None-MatchEtagIf-None-Match的优先级高。

If-Modified-SinceLast-Modified

If-Modified-Since: 请求头,资源最近修改时间,由浏览器高速服务器,是浏览器第一次访问服务器时返回的 Last-ModifiedLast-Modified:响应头,资源最近修改时间,由服务器告诉浏览器

服务器接收到请求后会根据此字段值判断是否使用缓存;使用缓存,则返回304;不使用缓存则返回新文件给客户端并更新Last-Modified响应头字段的值。

EtagIf-None-Match

If-None-Match:请求头,缓存资源标识,由浏览器告诉服务器,是浏览器第一次访问服务器返回的EtagEtag:响应头,资源标识,由服务器告诉浏览器

服务器接收到请求后会比较这两个值是否一样,一样就返回304,让客户端从缓存中读取,不一样就会返回新文件给客户端并更新Etag响应头字段的值。

缓存位置

内存memory cache、硬盘disk cacheService Workers

缓存配置

// 缓存时间1个月
add_header Cache-Control 'public, max-age=2592000'
// 使用协商缓存
add_header Cache-Control 'public, no-cache'

解决缓存引发的问题

缓存引发的问题就是最新资源不能及时更新,客户端在缓存有效期内显示的不是最新的资源。我们可以使用构建工具入Webpack等根据文件名/文件内容自动计算hash值来给文件命名,当内容或文件名发生改变的时候,构建出来的文件名也一定会不一样,这样也解决了强缓存还在有效期内的问题。

注意事项

  1. F5 会跳过强缓存规则,直接走协商缓存。
  2. CTRL + F5 会跳过所有缓存规则,和第一次请求一样。
  3. 项目中大多对HTML进行协商缓存,对CSS\JS\图片进行强缓存,文件名带上Hash。
  4. 强缓存是客户端在发起请求前,在客户端进行的是否使用缓存的判断;协商缓存是服务端收到客户端请求后,在服务端进行的是否使用缓存的判断。
  5. 命中强缓存则不会发请求去服务端;协商缓存是会对服务端请求的,协商缓存命中成功只返回响应头,协商缓存命中失败则返回最新的资源。
  6. 命中强缓存时,返回状态码是200;命中协商缓存时,返回状态码是304