浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires; Cache-control等)。但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下:
<meta http-equiv="Pragma" content="no-cache">
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。
下面我主要介绍HTTP协议定义的缓存机制
- Expires响应头字段
它的作用是在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
例如:响应头中Date头域为:Date: Mon,31 Dec 2017 04:25:57GMT。Expires为:2017-11-28 03:30:01 ,则表明这个时间点之前,可以使用缓存文件。缓存5分钟。
不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。 - Cache-control策略(重点关注)响应头字段
Cache-Control主要有以下几种类型:- 请求Request:
[1] no-cache ---- 不要读取缓存中的文件,要求向WEB服务器重新请求
[2] no-store ---- 请求和响应都禁止被缓存
[3] max-age: ---- 表示当访问此网页后的max-age秒内再次访问不会去服务器请求,其功能与Expires类似,只是Expires是根据某个特定日期值做比较。一但缓存者自身的时间不准确.则结果可能就是错误的,而max-age,显然无此问题.。Max-age的优先级也是高于Expires的。
[4] max-stale ---- 允许读取过期时间必须小于max-stale 值的缓存对象。
[5] min-fresh ---- 接受其max-age生命期大于其当前时间 跟 min-fresh 值之和的缓存对象
[6] only-if-cached ---- 告知缓存者,我希望内容来自缓存,我并不关心被缓存响应,是否是新鲜的.
[7] no-transform ---- 告知代理,不要更改媒体类型,比如jpg,被你改成png. - 响应Response:
[1] public ---- 数据内容皆被储存起来,就连有密码保护的网页也储存,安全性很低
[2] private ---- 数据内容只能被储存到私有的cache,仅对某个用户有效,不能共享
[3] no-cache ---- 可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端
[4] no-store ---- 请求和响应都禁止被缓存
[5] max-age: ----- 本响应包含的对象的过期时间
[6] Must-revalidate ---- 如果缓存过期了,会再次和原来的服务器确定是否为最新数据,而不是和中间的proxy
[7] max-stale ---- 允许读取过期时间必须小于max-stale 值的缓存对象。
[8] proxy-revalidate ---- 与Must-revalidate类似,区别在于:proxy-revalidate要排除掉用户代理的缓存的。即其规则并不应用于用户代理的本地缓存上。
[9] s-maxage ---- 与max-age的唯一区别是,s-maxage仅仅应用于共享缓存.而不应用于用户代理的本地缓存等针对单用户的缓存. 另外,s-maxage的优先级要高于max-age.
[10] no-transform ---- 告知代理,不要更改媒体类型,比如jpg,被你改成png.
- 请求Request:
例如:web服务器返回的Cache-Control头的值为max-age=300,即5分钟(和上面的Expires时间一致,这个不是必须的)。
If-Modified-Since(Request)/Last-Modified(Response)
Last-Modified/If-Modified-Since要配合Cache-Control使用
- Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
- If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。
If-None-Match(Request)/Etag(Response)
Etag/If-None-Match也要配合Cache-Control使用。
- Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
- If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
既生Last-Modified何生Etag?
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
- Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
- 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
- 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
基本转自浏览器缓存机制写得非常好,强烈推荐!