前段时间项目敏捷需求上线后,发现一个新增的logo图片显示不出。跟进之后发现是由于本地存在缓存,直接显示了本地的文件,而新增的图片没有更新。借这个机会研究了一下浏览器的缓存机制,分享出来~~
一、缓存的概念与好处
http缓存:当web请求抵达缓存时,如果本地有“已缓存”的副本,就可以从本地缓存设备而不是从原始服务器中提取这个文档。
缓存的好处:
1. 减少冗余的数据传输,节省了网费
2. 减少了服务器的负担,大大提高了网站的性能
3. 加快了客户端加载网页的速度
二、缓存机制
使用fiddler可以查看缓存信息:
Cache-control
指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。可取值:
public: 响应可被任何缓存区缓存
private: 响应只能作为私有缓存,是单个用户专用的,不能在用户之间共享
no-cache: 请求或响应消息不能缓存
no-store: 绝对禁止缓存(用于机密、敏感文件)
max-age: web中的文件被用户访问后多长时间内不需要重新访问服务器,比如max-age=5表示访问该网页后5秒内再次访问不回去服务器
min-fresh: 指示客户机可以接收响应时间小于当前时间加上指定时间的响应
max-state: 指示客户机可以接收超出超时期间的响应消息。如果指定max-state消息的值,那么客户机可以接收超出朝时期指定值内的响应消息
Last-Modifyied/If-Modified-Since
需要配合cache-control使用
Last-Modifyied: 服务器端文件的最后修改时间(response)
If-Modified-Since: 缓存文件的最后修改时间(request)
通过最后修改时间来判断缓存新鲜度
当资源过期时(max-age标识的时间之后),浏览器端想请求一个文档,首先检查本地缓存,发现存在这个文档的缓存。获取缓存中文档的最后修改时间If-Modified-Since,发送request给web服务器
服务器收到request,将服务器的文档修改时间Last-Modifyied,跟request header中的If-Modified-Since相比较,如果时间是一样的,说明还是最新的文件,web服务器会发送304 Not Modified给浏览器客户端,告诉客户端直接使用缓存里的版本,如下图:
如果文档已经更新了,web服务器将发送该文档的最新版本给浏览器客户端,如下图所示:
request中的If-Modified-Since等于request中的Last-Modifyied的时间,说明浏览器的缓存很新,web服务器返回304,告诉客户端使用本地缓存文件。
Etag
实体标签(Entity Tag)的缩写,根据实体内容生成一段hash字符串(类似于MD5或者SHA1之后的结果),可以标识资源的状态。当资源发生变化时,Etag也随之发生变化。需要配合cache-control使用
若If-Modified-Since和Etag的值一样,说明文件没有更新,服务器返回304,告诉客户使用本地缓存文件。否则服务器发送最新版本文件给浏览器。
Etag比Last-Modifyied的优势
1. 某些服务器不能精确得到文件的最后修改时间,这样就无法通过最后修改时间Last-Modifyied来判断文件是否更新了
2. 某些文件的修改非常频繁,在秒一下的时间内进行修改。Last-Modifyied只能精确到秒
3. 一些文件的最后修改时间变了,但是内容并未改变。服务器不希望客户端认为这个文件修改了。
Expire
Expire是web服务器响应消息投资段,在响应http请求时告诉浏览器在过期时间浏览器可以直接从浏览器缓存读取数据,而无需再次请求。
在2013.8.22 18:11:55之前可以使用缓存。发送缓存的时间是2013.7.24 8:38:36,即缓存近一个月。
Expire是http1.0的东西,现在浏览器均默认使用http1.1,所以它的作用基本忽略
上线更新文件后,若本地的缓存很顽固,不能直接更新,需要通过给文件加版本号的方式来强制更新文件。