一 强缓存
强缓存两个相关字段:Expires Cache-Control。
强缓存分为两种情况,一种是发送HTTP请求,一种不需要发送。
首先检查强缓存,这个阶段不需要发送HTTP请求。通过查找不同的字段来进行,不同的HTTP版本所以不同:
HTTP1.0版本,使用的是Expires,HTTP1.1使用的是Cache-Control
Cache-Control包括:
- max-age (单位为s)指定设置缓存最大的有效时间,定义的是时间长短。
- s-maxage (单位为s)同max-age,只用于共享缓存(比如CDN缓存)。
- public 指定响应会被缓存,并且在多用户间共享。
- private 响应只作为私有的缓存(见下图),不能在用户间共享
- no-cache 指定不缓存响应,表明资源不进行缓存。
- no-store 绝对禁止缓存。
- must-revalidate 指定如果页面是过期的,则去服务器进行获取。
-
Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间。在上面我们提到过,cache-control的优先级更高。 Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。这个方式有一个问题:「服务器的时间和浏览器的时间可能并不一致」,所以HTTP1.1提出新的字段Cache-Control代替它。
二 协商缓存
强缓存失效后,浏览器在请求头中携带响应的缓存Tag来向服务器发送请求,服务器根据对应的tag,来决定是否使用缓存。
缓存分为两种,Last-Modified 和 ETag,两者各有优势。
Last-modified
服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则返回码为304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为200,资源为服务器最新资源。
ETag
根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生。浏览器会将这串字符串传回服务器,验证资源是否已经修改,如果没有修改,过程如下:
既生Last-Modified何生Etag?
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
- Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
- 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
- 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
也就是说:
- Last-Modified是根据文件的修改时间作唯一标示,并且修改时间只能精确到秒级(同1s修改多次,无法生成新的Last-Modified)。
- Etag是根据资源内容在服务器端的唯一标识符,能够更加准确的控制缓存。