最近在做项目过程中需要对部分文件数据进行缓存,于是整理一些关于浏览器缓存机制的信息
概要总结:
1、Expires 过期时间
2、Cache-Control 缓存机制 [max-age=300]缓存时间 300 表示5分钟
3、Last-Modified 最后修改时间 对应在请求头部有If-Modified-Since
4、Etag 唯一标识 由服务器生成 对应在请求头部有If-No-Match
优先级:Etag > last-modified > Expires
浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires; Cache-control等)。
但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,
代码如下:
<meta http-equiv="Pragma" content="no-cache">
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。
使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。
下面我主要介绍HTTP协议定义的缓存机制。
1、Expires策略
Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
2、Cache-control策略
Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。
只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。
<1>http协议头Cache-Control:值可以是public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age
各个消息中的指令含义如下:
(1)Public指示响应可被任何缓存区缓存。
(2)Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
(3)no-cache指示请求或响应消息不能缓存
(4)no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
(5)max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
(6)min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
(7)max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
<2>Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since要配合Cache-Control使用。
(1)Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
(2)If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上If-Modified-Since,表示请求时间。
web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。
若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;
若最后修改时间较旧,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
<3>Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
(1)Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。
Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
(2)If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match(Etag的值)。
web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
3、提出问题:
<1>既然有了Last-Modified为何还要Etag?
答:HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
(1)Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
(2)如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
(3)有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。
因此Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
<2>哪些请求不能被缓存?
答:无法被浏览器缓存的请求:
(1)HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求
(2)需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
(3)经过HTTPS安全加密的请求(也有人经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存)
(4)POST请求无法被缓存
(5)HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存
4、注意事项:一般来说,可以把主页面(index.html)的缓存时间设置比较短,有的设置不缓存,这样保证页面文件是新的;
想要使用新的js文件,修改页面的<script src="test.js?version=V1.2" .....>,这样浏览器就是去拉新的js咯。
5、在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有: