说一说浏览器缓存

在项目中做资源优化的时候,其中一部分是关于浏览器缓存的内容,所以在网上找了关于这方面的知识去学习并应用,但是看完很多资料不免还是有几点疑惑:浏览器缓存是否由前端控制?if true, 该如何去设置;if false,那浏览器缓存该如何控制;希望接下来的描述可以说明这几个问题.

在说明这几个问题之前还是对浏览器缓存的几个属性做一个简单的介绍,关于浏览器缓存的定义和历史就不再赘述了,网上的文章实在是够看的了.

浏览器header中的属性

浏览器缓存的所有可缓存的资源都应该被缓存.

Expires和Cache-Control: max-age标头

这些标头用于指定相应时间段,浏览器可在指定的这段时间内使用已缓存的资源,而无需查看网络服务器是否提供了新版资源。这些缓存标头功能强大,没有任何应用条件限制。在设置这些标头并下载资源后,浏览器不会为资源发出任何GET请求,除非过期日期到期或达到时间最大值,亦或是用户清除了缓存。

Last-Modifed和ETag标头

这些标头可用于指定浏览器应如何确定用于缓存的文件是否相同。在Last-Modified标头中指定的是日期,而在ETag标头中指定的则可以是唯一标识资源的任意值(通常为文件版本或内容哈希值)。Last-Modified是功能“较弱”的缓存标头,因为浏览器会使用试探法来确定是否需要从缓存中抓取内容。

借助这些标头,浏览器可以通过在用户明确重新加载页面时发出条件式GET请求,有效地更新其已缓存资源。除非您在服务器端更改资源,否则条件式GET请求不会返回完整的响应,因此相较于完整GET请求,此类请求的延迟较小。

通常情况下我们对所有可缓存的资源都应设置缓存标头,指定一个Expires或Cache-Control: max-age以及一个Last-Modifed和ETag,但是没必要同时指定Expires和Cache-Control: max-age;或同时指定Last-Modified和ETag.如果这么做了,那么就会同时检查符合之后服务器才会返回304.

介绍完这些之后,就可以开始回答上面几个问题了.

浏览器缓存是否由前端控制?

这个问题的答案是浏览器缓存不能由js或者页面去设置,但是需要前端的服务器来配置,比如:apache,nginx等web服务器,恰好我们公司用的是tomcat服务器,让我又一顿好找,同时也理清了web服务器和应用服务器的概念,其中apache,nginx之类的是web服务器,tomcat并不是web服务器,它只是一个java servlet的容器.

该如何去控制浏览器缓存

虽然前端控制不了缓存,但是我们还是需要去配置服务器以达到我们的目的.就说一下apache,nginx和tomcat的三种配置.

apache配置浏览器缓存

###Apache Module mod_expires
使用Apache的mod_expires 模块来设置,这包括控制应答时的Expires头内容和Cache-Control头的max-age指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ExpiresActive On
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/html "access plus 30 minutes"
ExpiresByType text/css "access plus 30 minutes"
ExpiresByType text/txt "access plus 30 minutes"
ExpiresByType text/js "access plus 30 minutes"
ExpiresByType application/x-javascript "access plus 30 minutes"
ExpiresByType application/x-shockwave-flash "access plus 30 minutes"
或者
<ifmodule mod_expires.c>
<filesmatch "\.(jpg|gif|png|css|js)$">
ExpiresActive on
ExpiresDefault "access plus 1 year"
</filesmatch>
</ifmodule>

设置expires之后会自动输出会自动输出Cache-Control 的max-age 信息
apache官方文档

###忽略浏览器刷新请求

1
2
3
4
5
6
7
8
9
10
11
12
refresh_pattern -i \.gif$ 1440 100% 28800 ignore-reload
refresh_pattern -i \.jpg$ 1440 100% 28800 ignore-reload
refresh_pattern -i \.jpeg$ 1440 100% 28800 ignore-reload
refresh_pattern -i \.png$ 1440 100% 28800 ignore-reload
refresh_pattern -i \.bmp$ 1440 100% 28800 ignore-reload
refresh_pattern -i \.htm$ 60 100% 100 ignore-reload
refresh_pattern -i \.html$ 1440 50% 28800 ignore-reload
refresh_pattern -i \.xml$ 1440 50% 28800 ignore-reload
refresh_pattern -i \.txt$ 1440 50% 28800 ignore-reload
refresh_pattern -i \.css$ 1440 50% 28800 reload-into-ims
refresh_pattern -i \.js$ 60 50% 100 reload-into-ims
refresh_pattern . 10 50% 60

有关Squid中Expires的说明,请参考Squid官方中refresh_pattern介绍

###Apache设置Etag
在Apache中设置Etag的支持比较简单,只用在含有静态文件的目录中建立一个文件.htaccess, 里面加入:

1
FileETag MTime Size

这样就行了,详细的可以参考Apache的FileEtag文档页

nginx配置浏览器缓存

默认情况下,nginx对静态资源输出last-modified

配置expires

1
2
3
location~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
expires 30d;
}

详细介绍请参考nginx httpheaders模块

配置etag

Nginx中默认没有添加对Etag标识.但是可以通过第三方nginx- static-etags模块添加.

tomcat配置浏览器缓存

配置expires

使用tomcat的ExpiresFilter,ExpiresFilter是Apache mod_expires的Java Servlet API端口。此过滤器控制ExpiresHTTP头的设置和服务器响应中HTTP头的 max-age指令Cache-Control。 到期日期可以设置为相对于源文件上次修改的时间,或客户端访问时间。
在tomcat的web.xml中添加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<filter>
<filter-name>ExpiresFilter</filter-name>
<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
<init-param>
<param-name>ExpiresByType image</param-name>
<param-value>access plus 10 minutes</param-value>
</init-param>
<init-param>
<param-name>ExpiresByType text/css</param-name>
<param-value>access plus 10 minutes</param-value>
</init-param>
<init-param>
<param-name>ExpiresByType application/javascript</param-name>
<param-value>access plus 10 minutes</param-value>
</init-param>
</filter>
...
<filter-mapping>
<filter-name>ExpiresFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
或者
<init-param>
<param-name>ExpiresDefault</param-name>
<param-value>access plus 1 month</param-value>
</init-param>

<init-param>
<param-name>ExpiresDefault</param-name>
<param-value>access plus 4 weeks</param-value>
</init-param>

<init-param>
<param-name>ExpiresDefault</param-name>
<param-value>access plus 30 days</param-value>
</init-param>

详细参考资料请参考tomcat的Expires_Filter文档

配置Etag

在tomcat的配置文件context.xml中加入配置如下:

1
2
3
4
<context>
<Resources className="cn.fullstacks.tomcat.ETagFileDirContext" />
...
</context>

以上是对于浏览器缓存自己整理的一些资料,希望能帮助到大家如果有什么不对的地方欢迎指出.

你要是觉得好的话,可以点一下哦!