缓存实现的步骤
- 首先是当用户请求资源时,会判断是否有缓存,如果没有,则会向原服务器请求资源。
- 如果有缓存,则会进入强缓存的范畴,判断缓存是否新鲜
- 如果缓存新鲜,则会直接返回缓存副本给客户端。
- 如果缓存不新鲜了,则表示强缓存失败,将会进入到协商缓存。
- 协商缓存将判断是否存在
Etag和Last-Modified首部- 如果未发生变化,则表示命中了协商缓存,会重定向到缓存副本,将资源返回给客户端
- 否则的话表示协商缓存未命中,服务器会返回新的资源。
强缓存
服务端告知客户端缓存时间后,由客户端判断并决定是否使用缓存。
强缓存是通过 Expires 首部或 Cache-Control: max-age 来实现的。
Expires: 响应头,代表该资源的过期时间。Cache-Control: 请求/响应头,缓存控制字段,精确控制缓存策略。
server.js - demo
1 | const http = require('http') |
Expires(HTTP/1.0)
Expires 和 Cache-Control: max-age 都是用来标识资源的过期时间的首部。
由于 expires 是一个绝对时间,如果人为的更改时间,会对缓存的有效期造成影响,使缓存有效期的设置失去意义。因此在 http1.1 中我们有了 expires 的完全替代首部 cache-control:max-age
Cache-Control(HTTP/1.1)
除了可以设置 max-age 相对过期时间以外,还可以设置成如下几种值:
public,资源允许被中间服务器缓存。浏览器请求服务器时,如果缓存时间没到,中间服务器直接返回给浏览器内容,而不必请求源服务器。
private,资源不允许被中间代理服务器缓存浏览器请求服务器时,中间服务器都要把浏览器的请求透传给服务器。
no-cache,浏览器不做缓存检查。每次访问资源,浏览器都要向服务器询问,如果文件没变化,服务器只告诉浏览器继续使用缓存(304)。
no-store,浏览器和中间代理服务器都不能缓存资源。每次访问资源,浏览器都必须请求服务器,并且,服务器不去检查文件是否变化,而是直接返回完整的资源。
must-revalidate,可以缓存,但是使用之前必须先向源服务器确认。proxy-revalidate,要求缓存服务器针对缓存资源向源服务器进行确认。s-maxage:缓存服务器对资源缓存的最大时间。
Cache-Control 对缓存的控制粒度更细,包括缓存代理服务器的缓存控制。
协商缓存
由服务端决定并告知客户端是否使用缓存。
协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。
协商缓存是通过请求头 Last-Modified 或 Etag 来实现的。
Last-Modified标识的是文档最后修改时间Etag则是以文档内容来进行编码的。
Last-Modified
响应头,资源最近修改时间,由服务器告诉浏览器。
Last-Modified (上次修改时间)主要配合 If-Modified-Since 或者 If-Unmodified-Since 使用, 对比上次修改时间以验证资源是否需要更新
If-Modified-Since: 请求头
- 首次请求资源时,服务器在返回资源的同时,会在
Response Headers中写入Last-Modified首部,表示该资源在服务器上的最后修改时间。 - 当再次请求该资源时,会在
Request Headers中写入If-Modified-Since首部,此时的If-Modified-Since的值是首次请求资源时所返回的Last-Modified的值。 - 服务器接收到请求后,会根据
If-Modified-Since的值判断资源在该日期之后是否发生过变化。 - 如果没有,则会返回
304 Not Modified;如果变化了,则会返回变化过后的资源,同时更新Last-Modified的值。
资源未更新 network 面板截图
资源发生更新 network 面板截图
可以看到Last-Modified和If-Modified-Since标识的时间不一样
server.js- demo
1 | const http = require('http') |
Etag
响应头,资源标识,由服务器告诉浏览器。
Etag 和 If-None-Match 配合使用, (文件内容对比)对比资源的签名来决定是否使用缓存。
server.js- demo
1 | const http = require('http') |
总结与缓存方案
- 服务器和浏览器约定资源过期时间
Cache-Control: expires=xxx - 服务器告诉浏览器资源上次修改时间
Last-Modified - 增加相对时间的控制
Cache-Control: max-age=xxx - 增加文件内容对比,引入
Etag
缓存优先级
Pragma>Cache-Control>Expires>ETag>Last-Modified
参考与相关链接: