先说明下在高性能网站建设指南的14条性能规则中的其中几条:
- 减少HTTP请求
- 添加Expires头
- 禁用/配置Etag头
而这些恰恰就是跟浏览器缓存相关的内容。作为用户访问的最后一英里:浏览器,浏览器缓存对改善用户体验有着很重要的作用
但是浏览器缓存在不同浏览器的操作和首部字段的情况下,都会有不同的表现
简单的抛出几个场景:
- 地址栏输出地址后,点击回车,response是200, 304还是 200(from cache)?
- 点击浏览器刷新/F5刷新,response是200, 304还是 200(from cache)?
- 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-Control
,Cache-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-Since
和If-None-Match
,若资源未发生变更,则返回304,否则返回资源
在地址栏回车
Cache-control
为private
或must-revalidate
, 则只有第一次访问时会访问服务器(暂未验证过)- 之前请求头中
Cache-control
指定了max-age(有浏览器缓存),且缓存在有效期内,直接使用缓存,此时返回response status则为200 (from cache) - 之前请求头中
Cache-control
指定了max-age(有浏览器缓存),且缓存已失效,则请求服务器,请求头带上If-Modified-Since
和If-None-Match
,若资源未发生变更,则返回304,否则返回资源 Cache-control: no-cache
,则每次都会访问服务器
按后退按钮
Cache-control
为private
、must-revalidate
、max-age
, 不会重新访问服务器Cache-control: no-cache
,则每次都会访问服务器
按刷新按钮
无论Cache-control
为何值,均会重新访问服务器,因为刷新时浏览器请求头加入了Cache-Control:max-age=0
另外在打开chrome开发者工具时,基本行为跟之前说明一致,如果勾选disable cache
,则无论是地址栏输入地址回车访问,还是刷新访问,均会访问服务器,因为请求头中加入了Cache-Control:no-cache
和Pragma:no-cache
Web服务器开启Expires/ETag
apache配置Expires
可见apache使用mod_expires模块
nginx配置Expires
可见ngx_http_headers_module模块使用说明
另外对于ETag的取舍可见高性能网站建设指南 Rule13: Configure ETags