对于强缓存,服务器返回的静态资源响应头会设置一个强制缓存的时间,在缓存时间内,如刷新浏览器请求相同资源,在缓存时间未过期的情况下,则直接使用已缓存资源。如缓存资源已过期,执行协商缓存策略。
Expires
字段包含强缓存资源的过期时间通用消息头字段,通过指令来实现缓存机制。说明一下容易弄混的两个字段,其他指令参考指令大全[1]。
no-cache
在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)。
no-store
缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
Expires
过期时间为绝对时间,指未来某个时间点缓存过期。Cache-Control
为相对时间,相对于当前时间,如 60s 后缓存过期Expires
的优先级低于 Cache-Control
字段Cache-Control
和 Expires
时,以 Cache-Control
指令为准Expires
是 HTTP/1.0 提出的,其浏览器兼容性更好Cache-Control
是 HTTP/1.1 提出的,浏览器兼容性不佳,所以 Expires
和 Cache-Control
可以同时存在,在不支持 Cache-Control
的浏览器则以Expires
为准Pragma
是一个 HTTP1.0 中规定的通用首部,如果Cache-Control
不存在的话,它的行为与Cache-Control: no-cache
一致。强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行协商验证。Pragma
的值就只有一个,no-cache
,并且它的优先级比 Cache-Control
高。Cache-Control
,它的指令既可以用于强缓存又可应用于协商缓存策略中Cache-Control: no-cache
和 Cache-Control: max-age=0
的作用一样,强制要求发起请求给服务器进行验证 (协商资源验证)。当出现Pragma
字段或者Cache-Control:no-cache
时,就需要使用协商策略,常见的两对协商缓存字段如下
ETag/If-None-Match
Last-Modified/If-Modfied-Since
Etag 是 Entity tag 的缩写,可以理解为“被请求资源的摘要标识”,Etag 是服务端的一个资源的标识,在 HTTP 响应头中将其传送到客户端,类似这样,ETag:W/"50b1c1d4f775c61:df3"
ETag:W/"xxxxxxxx"
ETag:"xxxxxxx"
Nginx[2]的源码中 ETag 由 last_modified 和 content_length 拼接而成
etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
r->headers_out.last_modified_time,
r->headers_out.content_length_n)
- etag->value.data;
etag = header.last_modified + "-" + header.content_lenth
Last-Modified
和Content-Length
表示为十六进制组合而成。Lodash 网站请求检验
const LAST_MODIFIED = new Date(parseInt('5fc4907d', 16) * 1000).toJSON()
const CONTENT_LENGTH = parseInt('f48', 16)
console.log(LAST_MODIFIED) // 2020-11-30T06:26:05.000Z
console.log(CONTENT_LENGTH) // 3912
nginx
中ETag
由Last-Modified
和Content-Length
组成,那它便算是一个加强版的Last-Modified
了,那加强在什么地方呢?Last-Modified
只能作用于秒级的改变,而 nginx
中的 ETag
添加了文件大小的附加条件,不仅和修改时间有关,也和内容有关,使之更加精确。在 linux 中
mtime
:modified time
指文件内容改变的时间戳ctime
:change time
指文件属性改变的时间戳,属性包括mtime
。而在 windows
上,它表示的是creation time
Last-Modified
时一般会选择mtime
,表示文件内容修改的时间,来兼容 Windows 和 Linux。 r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = of.size;
r->headers_out.last_modified_time = of.mtime;
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
[2]https://github.com/nginx/nginx/blob/6c3838f9ed45f5c2aa6a971a0da3cb6ffe45b61e/src/http/ngx_http_core_module.c#L1582
[3]https://github.com/nginx/nginx/blob/4bf4650f2f10f7bbacfe7a33da744f18951d416d/src/http/modules/ngx_http_static_module.c#L217