Skip to main content

浏览器缓存

Http 缓存的工作原理#

浏览器发出的所有请求首先会转至浏览器缓存,用于检查是否存在可满足请求的有效缓存响应。如果存在匹配,则从缓存中读取响应,从而消除网络延迟和传输产生的数据成本。

HTTP 缓存的行为由 请求标头响应标头的一起控制。在理想情况下,您可以控制 Web 应用的代码(确定请求标头)和 Web 服务器的配置(确定响应标头)。

浏览器缓存请求过程#

浏览器加载资源时查询缓存过程,先看是否有cache-control 判断本地缓存是否过期,如果未过期直接使用本地缓存,如果已过期,则带上 If-Modified-Since If-None-Match 请求头服务器请求资源,服务器则判断是否内容过期,如果已过期则返回状态码200和内容体,如果未过期则返回状态码304告诉浏览器可以使用缓存。

直接使用本地缓存(无需网络请求) -> 校验内容(需要网络请求)

本地缓存判断#

缓存本地缓存是否过期 根据 Cache-Control or Expires来判断。优先级 Cache-Control > Expires

内容校验#

内容校验使用 响应头 ETag Last-Modified 和 请求头 If-Modified-Since If-None-Match 一起配合使用完成的。优先级 If-None-Match > If-Modified-Since

If-Modified-Since 取值 Last-Modified If-None-Match 取值 ETag

请求标头#

虽然有许多重要的标头应该包含在 Web 应用的传出请求中,但浏览器在发出请求时几乎总会自动进行设置。

影响检查新鲜度的请求标头,如 If-None-Match 和 If-Modified-Since,只是基于浏览器对 HTTP 缓存中当前值的理解而出现。

响应标头#

Cache-Control#

Cache-Control 通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。Cache-Control 流程图参考

Cache-Control 语法#

可缓存性#

Cache-control: no-cache 协商缓存验证:该值会命令浏览器在每次使用 URL 的缓存版本前都必须与服务器重新验证。

Cache-control: no-store 不使用任何缓存

Cache-control: public 响应可以由任何缓存存储

Cache-control: private 浏览器可以缓存文件,但中间缓存不能

过期#

Cache-control: max-age=seconds 设置缓存存储的最大周期 Cache-control: s-maxage=seconds 覆盖max-age或者Expires头

Cache-Control Demo#

禁止缓存#
Cache-Control: no-store
缓存静态资源#
Cache-Control:public, max-age=31536000

Expires#

expires 响应头包含日期/时间 在指定时间后缓存过期

如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略

expires 语法#

Expires: <http-date>

expires demo#

Expires: Wed, 21 Oct 2015 07:28:00 GMT

ETag#

ETag HTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。

如果给定URL中的资源更改,则一定要生成新的Etag值。

etag 语法#

ETag: W/"<etag_value>"ETag: "<etag_value>"

etag demo#

响应demo#
ETag: "1ga64df234525fcc55e2eftgy487lo09f2124fd4"ETag: W/"0912"
缓存未更改的资源#

ETag头的典型用例是和If-None-Match搭配使用来缓存未更改的资源。 如请求头:

If-None-Match: "1ga64df234525fcc55e2eftgy487lo09f2124fd4"

服务器将客户端的ETag(作为If-None-Match字段的值一起发送)与其当前版本的资源的ETag进行比较,如果两个值匹配(即资源未更改),服务器将返回不带任何内容的 304 未修改状态,告诉客户端缓存版本可用。

当与 If-Modified-Since 一同使用的时候,If-None-Match 优先级更高

Last-Modified#

The Last-Modified 是一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段。

语法#

Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

demo#

Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

缓存使用案例#

设置响应头#

cache-control: max-age=2592000,s-maxage=86400         etag: "ECF234DA05B6729F55BF5CC5F5CBBE89"last-modified: Thu, 24 Mar 2022 06:59:44 GMT

请求头demo#

if-modified-since: Thu, 24 Mar 2022 06:59:44 GMT    if-none-match: "ECF234DA05B6729F55BF5CC5F5CBBE89"