We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。
浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。这里只讨论 HTTP 缓存相关内容。
在具体了解 HTTP 缓存之前先来明确几个术语:
浏览器缓存主要是 HTTP 协议定义的缓存机制。HTML meta 标签,例如
<META HTTP-EQUIV="Pragma" CONTENT="no-store">
含义是让浏览器不缓存当前页面。但是代理服务器不解析 HTML 内容,一般应用广泛的是用 HTTP 头信息控制缓存。
大致分为两种:强缓存和协商缓存。强缓存如果命中缓存不需要和服务器端发生交互,而协商缓存不管是否命中都要和服务器端发生交互,强制缓存的优先级高于协商缓存。
Expires 如果命中,返回的from cache 不会产生http请求;而eTag,Last-Modified如果命中返回的是304。
匹配流程(已有缓存的情况下):
可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control 来表明规则。
概念:Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。
概念
缺点:Expires 是一个时间点,但服务端和客户端时间不统一,会造成提前过期或者过期还在使用的问题。并且 Expires 是 HTTP/1.0 的标准。略过时。
缺点
应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略
Cache-Control 可以由多个字段组合而成,主要有以下几个取值:
当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓存时间数值比指定时间的数值更小,那么客户端就接收缓存的资源。 另外,当指定 max-age 值为 0,那么缓存服务器通常需要将请求转发 给源服务器。
当服务器返回的响应中包含 max-age 指令时,缓存服务器将不对资源 的有效性再作确认,而 max-age 数值代表资源保存为缓存的最长时 间。
在没有禁用缓存并且没有超过有效时间的情况下,再次访问这个资源就命中了缓存,不会向服务器请求资源而是直接从浏览器缓存中取。
s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。
private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。
no-cache 客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接收缓存过的响应,“中间”的缓存服务器必须把客户端请求转发 给源服务器。 如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不能对资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资 源有效性进行确认,且禁止其对响应资源进行缓存操作。
no-store 禁止缓存,每次请求都要向服务器重新获取数据。
缓存的资源到期了,并不意味着资源内容发生了改变,如果和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源。
Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。
注意:如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。
(巧记:连起来既If Not Match Etag => response的Etag标签不匹配了 该重新返回新资源了)
由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd。服务器检查 ETag,一致时命中缓存返回304,不一致时进行Last-modified/ If-Modified-Since 的判断。
last-modified 和 Etag 区别:
last-modified 和 Etag 区别
注意:实际使用 ETag/Last-modified 要注意保持一致性,做负载均衡和反向代理的话可能会出现不一致的情况。计算 ETag 也是需要占用资源的,如果修改不是过于频繁,看自己的需求用 Cache-Control 是否可以满足。
该状态码表示客户端发送附带条件(指采用 GET 方法的请求报文中包含 If-Match,If-ModifiedSince,If-None-Match,If-Range,If-Unmodified-Since 中任一首部)的请求时,服务器端允许请求访问资源,但未满足条件的情况。
回到实际应用上来,首先要明确哪些内容适合被缓存哪些不适合。
不经常改变的文件:使用强缓存。 给 max-age 设置一个较大的值,一般设置 max-age=31536000
不经常改变的文件
比如引入的一些第三方文件、打包出来的带有 hash 后缀 css、js 文件。一般来说文件内容改变了,会更新版本号、hash 值,相当于请求另一个文件。
标准中规定 max-age 的值最大不超过一年,所以设成 max-age=31536000。至于过期内容,缓存区会将一段时间没有使用的文件删除掉。
可能经常需要变动的文件:使用协商缓存。 Cache-Control: no-cache / max-age=0
可能经常需要变动的文件
比如入口 index.html 文件、文件内容改变但名称不变的资源。选择 ETag 或 Last-Modified 来做验证,在使用缓存资源之前一定会去服务器端做验证,命中缓存时会比第一种情况慢一点点,毕竟还要发请求进行通信。
注意: 这里只描述了最基本的思路,实际使用 HTTP 缓存需要后端配合配置,具体情况具体对待,而且各方的实现并不一定完全按照标准来的,踩踩坑更健康。
HTTP 缓存机制一二三 《图解HTTP》
The text was updated successfully, but these errors were encountered:
讲得真好,点赞
Sorry, something went wrong.
谢谢😄
No branches or pull requests
Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。
浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。这里只讨论 HTTP 缓存相关内容。
在具体了解 HTTP 缓存之前先来明确几个术语:
浏览器缓存主要是 HTTP 协议定义的缓存机制。HTML meta 标签,例如
含义是让浏览器不缓存当前页面。但是代理服务器不解析 HTML 内容,一般应用广泛的是用 HTTP 头信息控制缓存。
HTTP 头信息控制缓存
大致分为两种:强缓存和协商缓存。强缓存如果命中缓存不需要和服务器端发生交互,而协商缓存不管是否命中都要和服务器端发生交互,强制缓存的优先级高于协商缓存。
匹配流程(已有缓存的情况下):
强缓存
可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control 来表明规则。
Expires
概念
:Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。缺点
:Expires 是一个时间点,但服务端和客户端时间不统一,会造成提前过期或者过期还在使用的问题。并且 Expires 是 HTTP/1.0 的标准。略过时。应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略
Cache-Control
Cache-Control 可以由多个字段组合而成,主要有以下几个取值:
当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓存时间数值比指定时间的数值更小,那么客户端就接收缓存的资源。 另外,当指定 max-age 值为 0,那么缓存服务器通常需要将请求转发 给源服务器。
当服务器返回的响应中包含 max-age 指令时,缓存服务器将不对资源 的有效性再作确认,而 max-age 数值代表资源保存为缓存的最长时 间。
在没有禁用缓存并且没有超过有效时间的情况下,再次访问这个资源就命中了缓存,不会向服务器请求资源而是直接从浏览器缓存中取。
s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。
private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。
no-cache
客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接收缓存过的响应,“中间”的缓存服务器必须把客户端请求转发 给源服务器。
如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不能对资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资 源有效性进行确认,且禁止其对响应资源进行缓存操作。
no-store 禁止缓存,每次请求都要向服务器重新获取数据。
协商缓存
缓存的资源到期了,并不意味着资源内容发生了改变,如果和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源。
If-Modified-Since(Request Header)/ Last-modified(Response Header)
Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。
注意:如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。
If-None-Match(Request Header)/ Etag(Response Header)
(巧记:连起来既If Not Match Etag => response的Etag标签不匹配了 该重新返回新资源了)
由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd。服务器检查 ETag,一致时命中缓存返回304,不一致时进行Last-modified/ If-Modified-Since 的判断。
last-modified 和 Etag 区别
:注意:实际使用 ETag/Last-modified 要注意保持一致性,做负载均衡和反向代理的话可能会出现不一致的情况。计算 ETag 也是需要占用资源的,如果修改不是过于频繁,看自己的需求用 Cache-Control 是否可以满足。
304 状态码
该状态码表示客户端发送附带条件(指采用 GET 方法的请求报文中包含 If-Match,If-ModifiedSince,If-None-Match,If-Range,If-Unmodified-Since 中任一首部)的请求时,服务器端允许请求访问资源,但未满足条件的情况。
实际应用
回到实际应用上来,首先要明确哪些内容适合被缓存哪些不适合。
考虑缓存的内容:
可缓存的内容又分为几种不同的情况:
不经常改变的文件
:使用强缓存。 给 max-age 设置一个较大的值,一般设置 max-age=31536000比如引入的一些第三方文件、打包出来的带有 hash 后缀 css、js 文件。一般来说文件内容改变了,会更新版本号、hash 值,相当于请求另一个文件。
标准中规定 max-age 的值最大不超过一年,所以设成 max-age=31536000。至于过期内容,缓存区会将一段时间没有使用的文件删除掉。
可能经常需要变动的文件
:使用协商缓存。 Cache-Control: no-cache / max-age=0比如入口 index.html 文件、文件内容改变但名称不变的资源。选择 ETag 或 Last-Modified 来做验证,在使用缓存资源之前一定会去服务器端做验证,命中缓存时会比第一种情况慢一点点,毕竟还要发请求进行通信。
注意: 这里只描述了最基本的思路,实际使用 HTTP 缓存需要后端配合配置,具体情况具体对待,而且各方的实现并不一定完全按照标准来的,踩踩坑更健康。
Reference
HTTP 缓存机制一二三
《图解HTTP》
The text was updated successfully, but these errors were encountered: