聊一聊浏览器缓存

先说明下在高性能网站建设指南的14条性能规则中的其中几条:

  • 减少HTTP请求
  • 添加Expires头
  • 禁用/配置Etag头

而这些恰恰就是跟浏览器缓存相关的内容。作为用户访问的最后一英里:浏览器,浏览器缓存对改善用户体验有着很重要的作用

但是浏览器缓存在不同浏览器的操作和首部字段的情况下,都会有不同的表现
简单的抛出几个场景:

  1. 地址栏输出地址后,点击回车,response是200, 304还是 200(from cache)?
  2. 点击浏览器刷新/F5刷新,response是200, 304还是 200(from cache)?
  3. chrome中打开开发者工具的情况下,上面两种场景又是怎么样的情况?

HTTP报文

先来看看与缓存相关的报文首部字段,加粗为现在经常使用到的

通用首部字段

通用首部字段:请求报文和响应报文都会使用的首部

字段名称 说明
Cache-Control 控制缓存的行为
Pragma 报文指令,http1.0的遗留物,值为“no-cache”时禁用缓存

请求首部字段

字段名称 说明
If-Match 比较实体标记(ETag)
If-None-Match 比较实体标记(与If-Match相反)
If-Modified-Since 比较资源的更新时间
If-Unmodified-Since 比较资源的更新时间(与If-Modified-Since相反)

响应首部字段

字段名称 说明
ETag 资源的匹配信息

实体首部字段

实体首部字段:针对请求报文和响应报文的实体部分使用的首部

字段名称 说明
Expires 实体主体过期的日期时间,http1.0的遗留物
Last-Modified 资源的最后修改日期时间

浏览器缓存

首部字段的演变

在HTTP1.0的时代,Web服务器使用Expires头来告诉浏览器对该实体主体进行缓存,在到达该日期之前,均可以使用该实体主体的缓存。

但是存在问题是服务器和客户端的时间并非一致,这就是Expires头的限制:要求两端时间同步。为了解决这个限制,在HTTP1.1时代引入了Cache-ControlCache-Control使用max-age指令指定组件被缓存多久,它以秒为单位定义了一个更新窗,对于不兼容HTTP1.1的浏览器,仍需保留Expires

而ETag是Web服务器和浏览器用于确认缓存组件的有效性的一种机制,但是需要留意ETag是依赖于服务器,后端为多台服务器,且不保持会话的情况下,ETag基本失效,导致不必要的请求,另外If-None-Match比If-Modified-Since具有更高的优先级,如果请求中同时出现了这两个头,则原始服务器禁止返回304,除非请求中的条件头字段全部一致。实际上如果没有If-None-Match头反而会更好一些(具体ETag建议见高性能网站建设指南 Rule13: Configure ETags

浏览器缓存

从上面可以看出浏览器缓存主要是有HTTP消息头中的Cache-control来控制的,常见的取值有:private,no-cache,max-age,must-revalidate,默认为private,其作用根据不同的浏览方式分为以下几种。

打开新窗口

  • 没有缓存情况下,访问服务器,返回response status则为200
  • 之前请求头中Cache-control指定了max-age(有浏览器缓存),且缓存在有效期内,直接使用缓存,此时返回response status则为200 (from cache)
  • 之前请求头中Cache-control指定了max-age(有浏览器缓存),且缓存已失效,则请求服务器,请求头带上If-Modified-SinceIf-None-Match,若资源未发生变更,则返回304,否则返回资源

在地址栏回车

  • Cache-controlprivatemust-revalidate, 则只有第一次访问时会访问服务器(暂未验证过)
  • 之前请求头中Cache-control指定了max-age(有浏览器缓存),且缓存在有效期内,直接使用缓存,此时返回response status则为200 (from cache)
  • 之前请求头中Cache-control指定了max-age(有浏览器缓存),且缓存已失效,则请求服务器,请求头带上If-Modified-SinceIf-None-Match,若资源未发生变更,则返回304,否则返回资源
  • Cache-control: no-cache,则每次都会访问服务器

按后退按钮

  • Cache-controlprivatemust-revalidatemax-age, 不会重新访问服务器
  • Cache-control: no-cache,则每次都会访问服务器

按刷新按钮

无论Cache-control为何值,均会重新访问服务器,因为刷新时浏览器请求头加入了Cache-Control:max-age=0

另外在打开chrome开发者工具时,基本行为跟之前说明一致,如果勾选disable cache,则无论是地址栏输入地址回车访问,还是刷新访问,均会访问服务器,因为请求头中加入了Cache-Control:no-cachePragma:no-cache

Web服务器开启Expires/ETag

apache配置Expires可见apache使用mod_expires模块
nginx配置Expires可见ngx_http_headers_module模块使用说明

另外对于ETag的取舍可见高性能网站建设指南 Rule13: Configure ETags

坚持原创技术分享,您的支持将鼓励我继续创作!.