下面再来看一个没有启用缓存的资源的例子:
没有包含Cache-Control
以及Expires
信息。
也有一些方便的在线检测服务,用于对网站速度给出建议,其中就会检测缓存设置情况。比如 Yahoo! 公司的 YSlow,以及百度站长工具等,都有相应的功能。大家可以去百度那里检测一下,目前是不需要登录即可检测的。
有些资源是很长时间不会改变的,比如网站的 logo 图片、jQuery 库、字体等,因此可以为它们设定「永不过期」的缓存时间,例如设定为 10 年。
有些时候我们会修改一些资源,比如更新了 jQuery 版本,或网站的 CSS 样式。如果这些资源已经被缓存,那么除非用户手工刷新页面,否则要等缓存自然过期之后用户才会获得新版本。如何在这种情况下强制浏览器重新下载呢?最有效的一个办法就是在这类资源的文件名中包含版本信息,并在更改之后对应地修改文件名。浏览器发现文件更换后,自然无法使用缓存,而会重新下载。
大部分情况下,对于其他图片、CSS、JavaScript 等资源的请求都来自一个单一的 HTML 文档。对于这类页面通常应该设定比较短的过期时间,或者干脆不设定。因为如果这类页面被缓存,那么页面中包含的资源的文件名等等信息都会一并被缓存,导致对它的更新难以确保立即对用户生效。
Query String 就是例如?key=val
的字符串,如
<script src="/static/js/func.js?v=a87ff8"></script>
这会阻止一部分较老的浏览器(包括 IE6 )对该资源进行缓存。
对于 Apache 服务器,可以通过 mod_expires 模块来设定Expires
HTTP 头或Cache-Control
HTTP 头的max-age
指令。编辑相应目录下的 .htaccess
文件,或直接对 Apache 的配置文件(根据服务器系统版本不同,可能为httpd.conf
或apache2.conf
等)作出修改。
使用ExpiresByType
可以按照文件的 MIME Type 设定某一类文件的过期日期。例如:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 2 weeks"
ExpiresByType image/x-icon "access plus 6 months"
ExpiresByType image/gif "access plus 6 months"
ExpiresByType image/png "access plus 6 months"
ExpiresByType image/jpeg "access plus 6 months"
ExpiresByType video/x-flv "access plus 6 months"
ExpiresByType application/pdf "access plus 6 months"
</IfModule>
其中access plus 1 week
表示将缓存过期设置为访问时间(即当前时间)之后的一周。如果将access
替换为modification
,则缓存过期会被设定为文件修改时间之后的一周。可以使用的时间单位包括:
不同的时间也可以进行组合,例如:
ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"
如果希望根据扩展名来指定缓存规则,可以使用FilesMatch
配合正则表达式。为了简洁,我这里只规定了ExpiresDefault
。它的优先级很低,只会在对应文件没有任何其他规则能够匹配(包括上层目录下的缓存规则)时生效。
<IfModule mod_expires.c>
<FilesMatch "\.(css|js)$">
ExpiresActive on
ExpiresDefault "access plus 1 week"
</FilesMatch>
</IfModule>
同理,也可以对某些文件启用特定的缓存策略。注意,文件名中的点(.
)是需要转义的。
<IfModule mod_expires.c>
<FilesMatch "^(example\.css|example\.js)$">
ExpiresActive on
ExpiresDefault "access plus 1 week"
</FilesMatch>
</IfModule>
对于静态文件,一个比较方便的做法是将它们全部放到一个目录下,并对该目录下的所有文件设定。但是,此处需要注意防止其他规则将ExpiresDefault
覆盖掉。
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 10 years"
</IfModule>