目录是缓存。为什么需要缓存? 快速缓存控制程序协商缓存etag/if-none-match last-modified/if-modified-since参考

什么是缓存

缓存:保存资源的副本,供下次请求时直接使用。

有两种类型的HTTP缓存:强缓存协商缓存

为什么需要缓存?缓存的主要作用是可以加快资源获取速度,提升用户体验,减少网络传输,缓解服务端的压力。。

强缓存强缓存是指直接读取浏览器的本地缓存,而无需将请求发送到服务端。 Chrome的网络上显示的HTTP状态代码为200。

在Chrome中,强制缓存分为磁盘缓存(存储在硬盘上)和内存缓存(内存缓存),存储位置由浏览器控制。 是否为强缓存由三个Header属性控制: Expires、Cache-Control和Pragma 3。

Expires Expires的值为HTTP日期,浏览器启动请求时,将根据系统时间和Expires的值进行比较。 如果系统时间超过Expires值,将禁用缓存。 为了与系统时间进行比较,如果系统时间和服务器时间不一致,则存在缓存的有效期会发生偏差的问题。 Expires的优先级在三个Header属性中最低。

Cache-Control Cache-Control是HTTP/1.1中添加的属性,在请求标头和响应标头中都可用。 一般属性值如下:

最大值:单位为秒。 缓存时间是以自开始以来的时间秒数计算的。 禁用超过间隔的秒数缓存no-cache :不使用强缓存。 必须与服务器验证缓存是否新鲜no-store :禁止使用缓存(包括协商缓存)每次都要求服务器提供最新的资源专用缓存。 中间代理、CDN等无法缓存此响应公共。 响应由中间代理、CDN等缓存。 可以在缓存过期之前使用最大恢复。 过期后,必须向服务器验证Pragma Pragma只有一个属性值no-cache。 效果和缓存控制的无缓存

在本地从express启动服务,以验证强缓存的三个属性。 代码如下

常数express=require (express ); 常数应用程序=express (; var options={ etag: false,//禁用协商缓存lastModified: false,//禁用协商缓存setheaders:(RES,pattation app.use (express.static (_ dirname ‘/public ‘,options ) ); app.Listen(3000; 在第一次加载中,页面向服务器请求数据,并将Cache-Control添加到响应头10秒钟。

在第二次加载中,可以看到Date标头的属性没有更新,浏览器直接使用强缓存,实际上没有发送请求。

10秒的超时时间过后,再次请求资源。

如果Pragma和Cache-Control同时存在,则Pragma的优先级高于Cache-Control。

协商缓存协商缓存是一种服务端缓存策略,用于确定请求是否可以在服务端命中缓存。

服务端判断客户端资源是否与服务端资源相同,如果匹配则返回304,反之则返回200,返回最新资源。

如果浏览器的强缓存已禁用,或者请求标头中设置了非强缓存,并且请求标头中设置了If-Modified-Since或If-None-Match,则为、 将这两个属性值传递给服务端验证是否命中协商缓存,如果命中协商缓存,则返回304状态,加载浏览器缓存,并在响应报头中设置last-mododch

etag/if-none-matche tag/if-none-match的值是一系列散列代码,当服务端文件发生更改时,将根据请求标头中的if-none-match和当前文件中的散列值进行更改如果散列代码是一系列以“W/”开头的字符串,则此时协商缓存检查为弱检查,仅在服务器上存在文件差异以触发散列值后缀变化时才真正请求资源,否则为304

最后修改/if-m

odified-Since

Last-Modified / If-Modified-Since 的值代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存。

本地通过 express 起一个服务来验证协商缓存,代码如下:

const express = require(‘express’);const app = express();var options = { etag: true, // 开启协商缓存 lastModified: true, // 开启协商缓存 setHeaders: (res, path, stat) => { res.set({ ‘Cache-Control’: ‘max-age=00’, // 浏览器不走强缓存 ‘Pragma’: ‘no-cache’, // 浏览器不走强缓存 }); },};app.use(express.static((__dirname + ‘/public’), options));app.listen(3001);

第一次请求资源:

第二次请求资源,服务端根据请求头中的 If-Modified-Since 和 If-None-Match 验证文件是否修改。

ETag / If-None-Match 的出现主要解决了 Last-Modified / If-Modified-Since 所解决不了的问题

当响应头部 Response Headers 同时存在 Last-Modified 和 Etag 的值时,会优先使用 Etag ;Last-Modified 只能精确到秒级;如果资源被重复生成,而内容不变,则 Etag 更精确

即:

如果文件的修改频率在秒级以下,Last-Modified / If-Modified-Since 会错误地返回 304如果文件被修改了,但是内容没有任何变化的时候,Last-Modified / If-Modified-Since 会错误地返回200 并返回资源

如果看完前面的文章后对HTTP 强缓存和协商缓存 还不是特别理解,可以继续看下面的文章,或许能帮到你;

如果前面的文章已经帮你理解了 HTTP 强缓存和协商缓存,则可以略过下面的文章。

强缓存

先看第一个图:

从上图可以看到,当初次请求时,浏览器会向服务器发起请求,服务器接收到浏览器的请求后,返回资源并返回一个 Cache-Control 给客户端,该 Cache-Control 一般设置缓存的最大过期时间。

接下来看第二个图:

从上图中可以看到,此时浏览器已经接收到 cache-control 的值,那么这个时候浏览器再次发送请求时,它会先检查它的 cache-control 是否过期,如果没有过期则直接从本地缓存中拉取资源,返回到客户端,而无需再经过服务器。

接下来看第三个图:

强制缓存有过期时间,那么就意味着总有一天缓存会失效。那么假设某一天,客户端的 cache-control 失效了,那么它就没办法从本地缓存中拉取资源。于是它会像第一张图一样,重新向服务器发起请求,之后服务器会再次返回资源和 cache-control 的值。
以上就是强制缓存的全过程。

协商缓存

先来看第一张图:

在上图中,表明了协商缓存的全过程。首先,如果客户端是第一次向服务器发出请求,则服务器返回资源和相对应的资源标识给浏览器。该资源标识就是对当前所返回资源的一种唯一标识,可以是Etag或者是Last-Modified,这两个字段将在图例结束后展开讲解。

之后如果浏览器再次发送请求时,浏览器就会带上这个资源标识。此时,服务端就会通过这个资源标识,可以判断出浏览器的资源跟服务端此时的资源是否一致,如果一致,则返回304,即表示Not Found 资源未修改。如果判断结果为不一致,则返回200,并返回资源以及新的资源标识。至此就结束了协商缓存的过程。

接下来看第二张图:

假设此时我们的协商缓存用 Last-Modified 来判断。当浏览器第一次发送请求时,服务器返回资源并返回一个 Last-Modified 的值给浏览器。这个 Last-Modified 的值给到浏览器之后,浏览器会通过 If-Modified-Since 的字段来保存 Last-Modified 的值,且 If-Modified-Since 保存在请求头当中。

之后当浏览器再次发送请求时,请求头会带着 If-Modified-Since 的值去找服务器,服务器此刻就会匹配浏览器发过来的 If-Modified-Since 是否和自己最后一次修改的 Last-Modified 的值相等。如果相等,则返回 304 ,表示资源未被修改;如果不相等,则返回200,并返回资源和新的 Last-Modified 的值。

接下来看第三张图:

假设此时我们的协商缓存用 Etag 来判断。当浏览器第一次发送请求时,服务器返回资源并返回一个 Etag 的值给浏览器。这个 Etag 的值给到浏览器之后,浏览器会通过 If-None-Match 的字段来保存 Etag 的值,且 If-None-Match 保存在请求头当中。

之后当浏览器再次发送请求时,请求头会带着 If-None-Match 的值去找服务器,服务器此刻就会匹配浏览器发过来的 If-None-Match 是否和自己最后一次修改的 Etag 的值相等。如果相等,则返回 304 ,表示资源未被修改;如果不相等,则返回 200 ,并返回资源和新的 Etag 的值。

参考 政采云前端团队:图解 HTTP 缓存星期一研究室:你知道304吗?图解强缓存和协商缓存