HTTP缓存到底是什么

什么是缓存

缓存是一种保存资源副本并在下次请求时直接使用副本的技术。缓存包括HTTP缓存和浏览器缓存。下文将详细讲解HTTP缓存

缓存的作用

  • 直接从本地获取缓存资源,降低了服务器压力,提升了加载速度
  • 通过复用以前获取的资源,可以显著提高网站和应用程序的性能

什么是http缓存

HTTP缓存就是当浏览器第二次向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有"要请求资源"的副本,就直接从浏览器缓存中提取,不再向服务端发送请求获取数据。

HTTP缓存大致分为强缓存和协商缓存 这两类。这两种缓存策略都是服务端设置 HTTP的Header 来实现的。
强制缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。

HTTP服务器常见响应返回状态码304,304代表告诉浏览器本地有缓存数据,可直接从本地获取,无需再发送请求向服务器获取

强缓存

直接从浏览器缓存的本地进行获取,不会去请求服务器。

当浏览器向服务器请求数据的时候,服务器会将数据和缓存的规则返回,在响应头的 header 中,有三个字段 ExpiresPragmaCache-Control共同决定。

Expires

Expires是HTTP1.0版本的属性,它的值是一个日期,是一个绝对时间,是当前返回数据缓存到期时间戳。当浏览器在进行请求的时候,系统时间会和expires时间做对比,如果系统时间超过了expires的值,表示浏览器缓存失效,会再向服务器端请求获取资源。

问题: 由于是系统时间做对比,如果手动改变电脑系统的时间,会有缓存有效期不准的问题,这就是HTTP1.0的问题,expires的优先级在三个header属性中最低的

Pragma

Pragma是http1.0版本的属性,它只有一个属性值,为no-cache,表示不使用强缓存,每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。但目前基本不使用Pragma

Pragma和Cache-Control类似,但Pragma: no-cache可以应用到HTTP 1.0 和HTTP 1.1,而Cache-Control: no-cache只能应用于HTTP 1.1

cache-control

cache-control是HTTP 1.1中新增的属性,在请求头和响应头中都可以使用,常见的属性值有

属性值 属性值代表意思
public 表示缓存可以被任何对象(包括发送请求的客户端、中间代理、CDN缓存等)
private 表示用户只能被浏览器缓存,不能作为共享缓存,即代理服务器和CDN不能缓存比响应
no-cache 不使用强缓存,需要与服务器验证是否为最新资源
no-store 禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源
max-age 单位是秒,缓存存储的最大周期,超过这个周期被认为过期
must-revalidate 当页面过期时,去服务器进行获取

强缓存优先级

如果三者同时存在,则 Pragma优先级>cache-control优先级 > expires优先级

使用

js 复制代码
// 控制浏览器不要缓存:
// 由于历史原因,设置不读取缓存的时候三者都需要设置。

response.setDateHeader("Expires", -1);

response.setHeader("Pragma", "no-cache");

response.setHeader("Cache-control", "no-cache");

// 控制浏览器使用缓存:

response.setDateHeader("Expires", System.currentTimeMillis()+1000*60*60*24);     //24小时

response.setHeader("Cache-control", "max-age=60");    //60秒(优先级更高)

协商缓存

每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回 304,否则重新完整响应。

协商缓存表示在使用本地的缓存之前,会先向服务器发一个请求,与服务器协商当前浏览器的缓存是否已经过期了,如果没过期,那么就使用本地的资源,如果过期了就去请求最新资源。协商缓存主要是解决强缓存资源不能及时更新的问题

协商缓存主要通过两种方式实现: Last-ModifiedIfModified-SinceEtagIf-None-Match

Last-Modified 与 IfModified-Since

  • Last-Modified和if-Modified-Since的值都是GMT格林尼治格式的事件字符串,代表的是文件的最后修改时间

  • 在客户端第一次请求服务器时,服务器会读取这个文件的最后修改时间,然后设置Last-Modified参数到响应头,参数值就是文件最后修改的时间戳,将其返回并存储在客户端

  • 客户端再次请求服务器时,请求头会带上上一次响应头的Last-Modified的时间,并将其放到if-Modified-Since请求头属性中

  • 服务端收到此请求头发现有if-Modified-Since,则将这个参数与Last-Modified进行对比,如果时间一致,则服务器端的资源没有变化,自动返回HTTP状态码304(Not Changed.)状态码,内容为空,客户端接到之后,就直接把本地缓存文件显示到浏览器中

  • 如果时间不一致,则服务器端资源发生改变或者重启服务器,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中

Etag 与 If-None-Match

  • Etag和If-None-Match的值是一串hash码,代表的是一个资源的标识符

  • Etag是服务端为文件生成的一个唯一标识,资源的每一次变化都会导致Etag的变化,即当客户端第一次请求服务器时,服务器端会在响应头塞进Etag以及其计算出的字符串参数,将其返回给客户端

  • 客户端接收到Etag后,在第二次请求会带上If-None-Match的参数,再与被请求资源的唯一标识Etag进行对比,如果相同,则没有修改,响应返回304,浏览器直接从缓存中获取资源;反之,返回200,响应整个资源内容

协商缓存优先级

如果Etag和Last-Modified同时存在时,则 Etag优先级>Last-Modified优先级

强缓存和协商缓存的优先级

如果强缓存和协商缓存同时存在,如果强缓存还在生效期则强制缓存覆盖协商缓存,对比缓存不生效;如果强缓存不在有效期,协商缓存生效。则强缓存优先级 > 协商缓存优先级

总结

通过前文,我们了解到 HTTP 缓存主要分强制缓存和协商缓存。强制缓存由 Cache-Control(HTTP1.1),Exipres(HTTP1.0)控制。浏览器直接读本地缓存,不会再跟服务器端交互,状态码 200。协商缓存由 Last-ModifiedIfModified-SinceEtagIf-None-Match实现,每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回 304,否则重新完整响应,返回200。

相关推荐
&白帝&21 分钟前
uniapp中使用picker-view选择时间
前端·uni-app
谢尔登28 分钟前
Babel
前端·react.js·node.js
ling1s28 分钟前
C#基础(13)结构体
前端·c#
卸任35 分钟前
使用高阶组件封装路由拦截逻辑
前端·react.js
lxcw1 小时前
npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED
前端·npm·node.js
秋沐1 小时前
vue中的slot插槽,彻底搞懂及使用
前端·javascript·vue.js
这个需求建议不做1 小时前
vue3打包配置 vite、router、nginx配置
前端·nginx·vue
QGC二次开发1 小时前
Vue3 : Pinia的性质与作用
前端·javascript·vue.js·typescript·前端框架·vue
云草桑1 小时前
逆向工程 反编译 C# net core
前端·c#·反编译·逆向工程
布丁椰奶冻1 小时前
解决使用nvm管理node版本时提示npm下载失败的问题
前端·npm·node.js