本文主要讲 http 缓存 (资源缓存)
- 本文讲了缓存的前世今生, 但好像最重要的知识点并没有讲到(就当我不会吧; 好吧 真不会 (´•̥̥̥ω•̥̥̥`) )
缓存的形式
Memory Cache(内存缓存)
- 时间间隔较短时, 重复请求相同的资源时, 一般情况下资源还在内存中, 那直接从内存中获取资源, 这种方式是最快的资源获取方式
- 通常情况下, 关闭 tab 页签时, 会清除内存中的资源
Disk Cache(硬盘缓存)
- 把资源存储到本机的硬盘上, 当再次需要数据时, 可以直接从硬盘上获取
- 缓存的时间一般会根据请求头的设置而定
CDN 缓存
- 当用户请求资源时会经过 CDN 服务器, 服务会对可以缓存的资源进行缓存
- 当有另外的用户也需要这个资源时, CDN 服务器就可以直接返回资源, 不需要再找原服务器要了
服务端缓存
- 当一些数据需要服务端进行大量计算才能获得时, 服务端为了避免重复的处理影响服务器性能, 开发人员会对处理过的数据进行缓存, 下次再需要时直接取缓存中的数据
- 服务端缓存一般是一些接口的缓存处理, 我们前端不需要过多关注, 了解即可.
- 缓存时效可能根据数据的性质不同而不同, 这个不是特别熟这里不做详细讲解
缓存的设置/处理
不对缓存进行设置/处理
- 这个时候浏览器会根据自己的一套逻辑进行处理
- 例如: 默认会对 js 资源缓存x天, css 缓存 y 天等
通过 meta 标签设置(不要使用 / 可能已经不生效)
<meta http-equiv="Cache-Control" content="max-age=7200" />
// or
<meta http-equiv="Cache-Control" content="no-cache" />
- 虽然说这个可以控制缓存, 但请不要使用, 只需要知道曾经可以这样做即可
设置缓存请求头
缓存优先级: Cache-Control > Expires > Etag > Last-Modified
Last-Modified / If-Modified-Since(缓存校验)
- Last-Modified(服务端返回): 标记着文件在服务端最后被修改的时间
- If-Modified-Since(客服端发起): 本地文件的修改时间(可以理解为上次请求返回的 Last-Modified)
- 当第二次请求数据时, 客户端会带上 If-Modified-Since 请求头, 服务端判断后如果文件没有更改, 直接返回 304 状态码, 请求没有响应体
- 客户端在收到 304 状态码时, 直接使用本地缓存的资源.
- 请求过程没有进行数据传递, 效率会高跟多
Etag / If-None-Match(缓存校验)
-
Etag(服务端返回): 请求数据成功后, 返回数据时会携带 Etag 请求头, 他是根据文件生成的一个字符串, 当文件变化时他也会跟着改变
- 生产算法这个不细讲, 感兴趣的同学可以自行百度.
- 在进行文件切片上传(大文件上传/断点续传)时也需要生成文件唯一值 应该是类似的, 可以同步关注一下
-
If-None-Match(客服端发起): 上次返回的 Etag 值
整个流程基本上和 (Last-Modified / If-Modified-Since) 很类似
那相比 (Last-Modified / If-Modified-Since) 有什么优势呢?
- 如果文件更新(修改时间更新)但是内容没有变, 那使用 Last-Modified 时, 就需要重新请求资源
- Last-Modified 返回的时间一般是以秒为单位的, 如果一个文件1秒内更新了多次, 那就会出现问题
- 有一些服务器不能精确得到文件的修改时间
Expires(缓存校验)
- 服务器设置 Expires 字段为一个日期, 客户端请求该资源时将这个日期与客户端当前日期进行比对
- 如果当前时间小于这个日期, 则表示资源未过期, 使用缓存
- 如果当前时间大于这个日期, 则表示资源已过期, 客户端就会重新请求该资源
这样做其实存在一个问题: 我们依赖客户端时间, 就会因为客户端的时间不准确导致判断错误
- 如果客户端时间晚于服务器的时间, 会导致资源还未过期就重新请求
- 反之, 会导致客户端还在使用过期的旧资源.
Cache-Control
- Cache-Control 是在 HTTP/1.1 中才有, 算是一个"新"的API (新是相对以前的处理, 因为现在已经有 HTTP3 了)
- 可选的参数有很多: public, private, no-cache, no-store, max-age= 等
- 不展开讲了, 可以参考: developer.mozilla.org/zh-CN/docs/…
具体实施(处理方式)
- 我们一般会使用 nginx 服务器做代理, 通过设置 nginx 配置来设置 Cache-Control 请求头
- 一般情况下我们会设置 html 文件不做任何缓存 no-store, 其他文件可以设置一个比较长的缓存时间
- 我们的入口文件一般是 html, 每次上线后更新 html 内的引用即可保证我们的资源引用都是正确的
- 其他: nginx 还可以实现 gzip 压缩, 感兴趣的自行百度;
总结
-
缓存形式
- 内存缓存 => 硬盘缓存 => CDN 缓存 => 服务端缓存
-
缓存的设置/处理方式
- 不设置(默认行为) => 设置 meta 标签 => 设置缓存请求头
-
缓存请求头
- Last-Modified => Etag => Expires => Cache-Control
-
有用的知识(你应该学习的知识点, 但没讲 (´•༝•`) ): Cache-Control API
相关文档
前端应该了解的 Nginx 知识
Cache-Control 使用