当前位置: 代码迷 >> 综合 >> 浏览器缓存控制三种方式(Expires、Last-Modified、Etag)
  详细解决方案

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

热度:104   发布时间:2023-09-06 22:59:20.0

当请求一个页面时,如果浏览器使用本地缓存,因此我们经常会看到一个HTTP请求为304状态。或者显示200状态,在chrome下标注是from cache,在火狐下会标注BFCache;

我们希望在服务器端更新了静态文件(如css、js、图片),能够在客户端得到及时的更新,但又不想让浏览器每次请求都从服务器端获取静态资源。那么就需要了解一些下面的知识:

Last-Modified / If-Modified-Since

当浏览器第一次请求一个url时,服务器端的返回状态码为200,同时HTTP响应头会有一个Last-Modified标记着文件在服务器端最后被修改的时间。

 

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

 

浏览器第二次请求上次请求过的url时,浏览器会在HTTP请求头添加一个If-Modified-Since的标记,用来询问服务器该时间之后文件是否被修改过。

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

如果服务器端的资源没有变化,则自动返回304状态,使用浏览器缓存,从而保证了浏览器不会重复从服务器端获取资源,也保证了服务器有变化是,客户端能够及时得到最新的资源。

Etag / If-None-Match

当浏览器第一次请求一个url时,服务器端的返回状态码为200,同时HTTP响应头会有一个Etag,存放着服务器端生成的一个序列值。

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

浏览器第二次请求上次请求过的url时,浏览器会在HTTP请求头添加一个If-None-Match的标记,用来询问服务器该文件有没有被修改。

 浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

 

Etag 主要为了解决 Last-Modified 无法解决的一些问题:

1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;

2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)

3、某些服务器不能精确的得到文件的最后修改时间;

 

Expires

<meta http-equiv="expires" content="Fri, 22 Aug 2014 00:52:49 GMT" />

HTTP 1.0,设置缓存的截止时间,在此之前,浏览器对缓存的数据不重新发请求。它与Last-Modified/Etag结合使用,用来控制请求文件的有效时间,当请求数据在有效期内,浏览器从缓存获得数据。Last-Modifed/Etag能够节省一点宽带,但是还会发一个HTTP请求。

Catch-Control

<!--Cache-Control: max-age=秒 -->
<meta http-equiv="Cache-Control" content="max-age=120"/>

HTTP 1.1,设置资源在本地缓存多长时间。

如果Cache-Control与expires同时存在,Cache-Control生效。expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。

用户操作与缓存

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

禁止缓存

<!--禁止浏览器本地缓存 -->
<meta http-equiv="Cache-Control" content="no-cache"/><!-- 或者 -->
<meta http-equiv="Cache-Control" content="max-age=0"/>

还有POST请求不使用缓存,HTTP响应头不包含Last-Modified/Etag,也不包含Cache-Control/Expires不会使用缓存。

除非有特殊需求,最好还是不要禁用缓存,毕竟是用缓存能节省宽带,节省服务器资源,节省money...

浏览器第一次请求过程

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

浏览器第二次请求过程

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

我们希望服务器端更新了文件,客户端可以及时的更新文件,根具上面流程,我们需要针对静态文件的响应头添加expires,设置为永久过期,浏览器每次请求静态文件,就会询问服务器文件有没有做过更改,如果更改了就从服务器端获取资源,否则直接使用缓存。  

apache的配置:

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

#开启mod_expires模块
LoadModule expires_module modules/mod_expires.soExpiresActive On
ExpiresDefault "access plus 0 seconds" #默认缓存0s
<Directory  "根目录">#Options FollowSymLinks#AllowOverride allOrder deny,allowAllow from all#ExpiresByType application/* "access plus 0 seconds"#ExpiresByType image/* "access plus 0 seconds"#ExpiresByType text/css "access plus 0 seconds"
</Directory>

浏览器缓存控制三种方式(Expires、Last-Modified、Etag)

这样的做法有个弊端,就是每次请求都会询问服务器端资源是否过期,当然还有更好的办法。

不管怎样,适合自己项目的就是好方法。

 

  相关解决方案