HTTP 缓存
HTTP 缓存是一种常用的优化技术,用于减少网络传输和提高网页加载速度。在 HTTP 缓存中,有两种常见的缓存策略,分别是强制缓存和协商缓存。
缓存的原理是在首次请求后保存一份请求资源的响应副本,当用户再次发起相同请求后,如果判断缓存命中则拦截请求,将之前存储的响应副本返回给用户,从而避免重新向服务器发起资源请求。
强制缓存
强制缓存是一种缓存策略,其中浏览器在请求资源时,直接从本地缓存中读取资源,并且不发送请求到服务器。
响应头的部分信息:
Access-Control-Allow-Origin: *
age: 397887
cache-control: max-age=2592000
content-length: 40830
content-encoding: gzip
content-type: text/css
expires: Sat, 25 Sep 2021 02:24:26 GMT
实现 HTTP 强制缓存可以通过设置以下两个响应头字段:
expires 是在
HTTP1.0
协议中声明的用来控制缓存失效日期时间戳的字段,它由服务器端指定后通过响应头告知浏览器,浏览器在接收到带有该字段的响应体后进行缓存。若之后浏览器再次发起相同的资源请求,便会对比 expires 与本地当前的时间戳,如果当前请求的本地时间戳小于 expires 的值,则说明浏览器缓存的响应还未过期,可以直接使用而无须向服务器端再次发起请求。只有当本地时间戳大于 expires 值发生缓存过期时,才允许重新向服务器发起请求。
从上述强制缓存是否过期的判断机制中不难看出,这个方式存在一个很大的漏洞,即对本地时间戳过分依赖,如果客户端本地的时 间与服务器端的时间不同步,或者对客户端时间进行主动修改,那么对于缓存过期的判 断可能就无法和预期相符。
Cache-Control
:Cache-Control
字段是一个更加灵活和强大的控制缓存行为的方式。HTTP 1.1
协议新增。它是一个由多个指令组成的逗号分隔的字符串,例如
Cache-Control: max-age=3600, private
。常用的指令包括:max-age
: 指定资源的最大缓存时间,单位为秒。例如Cache-Control: max-age=3600
表示资源在缓存中最多可以被保存 3600 秒(1 小时)。private
: 表示资源只能被单个用户缓存,不允许在共享缓存中缓存。public
: 表示资源可以被共享缓存和单个用户缓存。no-cache
: 表示资源需要在每次请求时都向服务器验证是否过期,不使用缓存(no-cache 并非像字面上的意思不使用缓存,其表示为强制进行协商缓存,即对于每次发起的请求都不会再去判断强制缓存是否过期,而是直接与服务器协商来验证缓存的有效性,若缓存未过期,则会使用本地缓存。)。no-store
: 表示禁止使用任何缓存策略,客户端的每次请求都需要服务器端给予全新的响应。
no-cache
和no-store
是两个互斥的属性值,不能同时设置。
Cache-Control
字段的优先级比 Expires
字段高,即如果同时存在这两个字段,Cache-Control
字段会覆盖 Expires
字段。使用 Cache-Control
字段可以更精确地控制缓存的行为,并且不受时钟同步等限制,因此在现代的 Web 开发中更加常用和推荐使用。
协商缓存
ETag
和 Last-Modified
是 HTTP 响应头中的字段,用于实现协商缓存的机制,以便在服务器端判断资源是否已经过期,从而控制缓存的更新。
ETag
:ETag
字段是一个由服务器生成的唯一标识符,用于表示资源的版本号或者内容的摘要。当客户端请求资源时,服务器会将资源的ETag
值包含在响应头中,客户端可以将该值保存起来。当客户端再次请求资源时,可以将保存的ETag
值包含在请求头中,通过与服务器端比较ETag
值来判断资源是否发生了变化。如果资源的ETag
值没有发生变化,服务器可以返回一个空的响应,表示资源未修改,客户端可以继续使用缓存的资源;如果资源的ETag
值发生了变化,服务器会返回新的资源,并更新ETag
字段的值。Last-Modified
:Last-Modified
字段表示资源在服务器上的最后修改时间。服务器在响应头中返回资源的Last-Modified
值,客户端可以将该值保存起来。当客户端再次请求资源时,可以将保存的Last-Modified
值包含在请求头中,通过与服务器端比较Last-Modified
值来判断资源是否发生了变化。如果资源的Last-Modified
值没有发生变化,服务器可以返回一个空的响应,表示资源未修改,客户端可以继续使用缓存的资源;如果资源的Last-Modified
值发生了变化,服务器会返回新的资源,并更新Last-Modified
字段的值。
ETag
和 Last-Modified
字段可以配合使用,或者分别单独使用,来实现协商缓存的机制,从而避免不必要的资源传输和提升缓存效果。其中,ETag
的优先级比 Last-Modified
高,即如果同时存在这两个字段,服务器会优先检查 ETag
值来判断资源是否发生了变化。