2021-06-21 12:48:04
一、缓存概述
缓存是一种存储数据的技术,用于减少不必要的数据传输,提升网站性能,加快客户端加载速度,并优化用户体验。然而,缓存也可能导致客户端信息更新滞后的问题。当浏览器请求某个文件时,服务端会在响应头(response header)中对该文件进行缓存配置,包括缓存的时间和类型,这些均由服务端控制。
二、缓存类型
浏览器缓存包括两种类型:强缓存(本地缓存)和协商缓存。
强缓存
定义:强缓存是直接从缓存中获取资源而不经过服务器。
判断依据:浏览器在请求某一资源时,会先获取该资源的缓存header信息,判断是否命中强缓存。这主要依赖于cache-control和expires这两个header字段。
expires:HTTP 1.0的规范,值为一个绝对时间的GMT格式时间字符串。如果发送请求的时间在expires之前,则本地缓存有效,否则发送请求到服务器获取资源。
cache-control:HTTP 1.1的规范,主要利用该字段的max-age值进行判断。它是一个相对值,根据资源第一次请求时间和Cache-Control设定有效期计算出一个资源过期时间,如果请求时间在过期时间之前,则命中缓存。
优先级:如果cache-control与expires同时存在,cache-control的优先级高于expires。
状态码:从缓存中获取资源时,状态码为200。
协商缓存
定义:协商缓存是由服务器来确定缓存资源是否可用的。如果强缓存未命中,浏览器会发送请求到服务器,携带第一次请求返回的缓存header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据这些信息判断协商缓存是否命中。
判断依据:
Last-Modified/If-Modified-Since:二者的值都是GMT格式的时间字符串。服务器在返回资源时,会在response header中加上Last-Modified,表示资源在服务器上的最后修改时间。浏览器再次请求资源时,会在request header中加上If-Modified-Since,其值为上一次请求时返回的Last-Modified的值。服务器根据这两个值判断资源是否有变化。
Etag/If-None-Match:这两个值是由服务器生成的每个资源的唯一标识符,只要资源有变化,这个值就会改变。其判断过程与Last-Modified/If-Modified-Since类似,但更精确。
状态码:若协商缓存命中,服务器返回304状态码,不返回资源内容,仅更新缓存中的header信息;若未命中,则返回最新的资源内容。
三、强缓存与协商缓存的区别
四、缓存header字段的详细解释
强缓存相关header字段
expires:如上所述,为HTTP 1.0的规范,用于设置资源的过期时间。
cache-control:HTTP 1.1的规范,除了max-age外,还有以下常用设置值:
no-cache:不使用本地缓存,需要使用协商缓存。
no-store:直接禁止浏览器缓存数据。
public:可以被所有用户缓存,包括终端用户和CDN等中间代理服务器。
private:只能被终端用户的浏览器缓存。
协商缓存相关header字段
Last-Modified:资源在服务器上的最后修改时间。
If-Modified-Since:浏览器再次请求资源时,携带的上一次请求时返回的Last-Modified的值。
Etag:服务器生成的每个资源的唯一标识符。
If-None-Match:浏览器再次请求资源时,携带的上一次请求时返回的Etag的值。
五、ETag与Last-Modified的比较
虽然Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,但ETag的出现解决了Last-Modified的一些难题,如周期性更改但内容不变的文件、修改非常频繁的文件以及服务器无法精确获取文件最后修改时间的情况。因此,ETag能够更准确地控制缓存。在实际应用中,Last-Modified与ETag可以一起使用,服务器会优先验证ETag,一致的情况下才会继续比对Last-Modified,最后才决定是否返回304。


综上所述,强缓存和协商缓存是浏览器缓存的两种重要机制,它们共同作用于提升网站性能和用户体验。在实际应用中,开发者应根据具体需求合理配置缓存策略,以实现最佳效果。