缓存技术之HTTP缓存-强制缓存

682 阅读4分钟

这是我参与8月更文挑战的第15天,活动详情查看: 8月更文挑战

前言

HTTP缓存应该算是前端开发中最常接触的缓存机制之一,它又可细分为强制缓存与协商缓存,二者最大的区别在于判断缓存命中时,浏览器是否需要向服务器端进行询问以协商缓存的相关信息,进而判断是否需要就响应内容进行重新请求

强制缓存

对于强制缓存而言,如果浏览器判断所请求的目标资源有效命中,则可直接从强制缓存中返回请求响应,无需与服务器进行任何通信。

一段常见的响应头的部分信息:

access-control-allow-origin: *
age: 734978
cache-control: max-age=3153600
content-length: 40830
content-type: image/jpeg
date: Sun, 15 Aug 2021 22:08:28 GMT
expires: Sun, 15 Aug 2022 22:08:28 GMT 

其中与强制缓存相关的两个字段是expires和cache-control,expires是在HTTP1.0协议中声明的用来控制缓存失效日期时间戳的字段,它由服务器端指定后通过响应头告知浏览器,浏览器在接收到带有该字段的响应体后进行缓存。

若之后浏览器再次发起相同的资源请求,便会对比expires与本地当前的时间戳,如果当前请求的本地时间戳小于expires的值,则说明浏览器缓存的响应还未过期,可以直接使用而无须向服务器端再次发起请求。只有当本地时间戳大于expires值发生缓存过期时,才允许重新向服务器发起请求。

从上述强制缓存是否过期的判断机制中不难看出,这个方式存在一个很大的漏洞,即对本地时间戳过分依赖,如果客户端本地的时间与服务器端的时间不同步,或者对客户端时间进行主动修改,那么对于缓存过期的判断可能就无法和预期相符。

为了解决expires判断的局限性,从HTTP1.1协议开始新增了cache-control字段来对expires的功能进行扩展和完善。从上述代码中可见cache-control设置了max-age=31536000的属性值来控制响应资源的有效期,它是一个以秒为单位的时间长度,表示该资源在被请求到后的31536000秒内有效,如此便可避免服务器端和客户端时间戳不同步而造成的问题。除此之外,cache−cotrol还可配置一些其他属性值来更准确地控制缓存,下面来具体介绍。

no-cache和no-store

设置no−cache并非像字面上的意思不使用缓存,其表示为强制进行协商缓存,即对于每次发起的请求都不会再去判断强制缓存是否过期,而是直接与服务器协商来验证缓存的有效性,若缓存未过期,则会使用本地缓存。设置no-store则表示禁止使用任何缓存策略,客户端的每次请求都需要服务器端给予全新的响应。no-cache和no-store是两个互斥的属性值,不能同时设置。

private和public

private和public也是cache−control的一组互斥属性值,它们用以明确响应资源是否可被代理服务器进行缓存。若资源响应头中的 cache-control字段设置了public属性值,则表示响应资源既可以被浏览器缓存,又可以被代理服务器缓存。private限制了响应资源只能被浏览器缓存,若未显式指定则默认值为private。

max-age和s-maxage

max−age属性值会比s−maxage更常用,它表示服务器端告知客户端浏览器响应资源的过期时长。在一般项目的使用场景中基本够用,对于大型架构的项目通常会涉及使用各种代理服务器的情况,这就需要考虑缓存在代理服务器上的有效性问题。这便是s-maxage存在的意义,它表示缓存在代理服务器中的过期时长,且仅当设置了public属性值时才有效。

由此可见cache-control能作为expires的完全替代方案,并且拥有其所不具备的一些缓存控制特性,在项目实践中使用它就足够了,目前expires还存在的唯一理由是考虑可用性方面的向下兼容。