大多数网页(包括网页引用的资源,例如CSS文件、图片文件,JavaScript文件等)变化的频度非常高。这些资源都需要花时间从网上下载,他 们会增加网页加载的时间。HTTP缓存允许这些资源被浏览器或代理存储或者缓存。一旦资源被缓存,随后访问页面时,浏览器或代理将直接找本地缓存的副本而不是再次下载。因此使用缓存是双赢的:节省了往返时间,减少了大量HTTP去请求需要的资源,同时大幅缩减响应负荷的总体尺寸。缓存除了可以戏剧性的缩减多数用户访问页面的加载时间之外,还能极大减小带宽和站点主机的费用。
- 利用浏览器的缓存(Leverage browser caching )
- 利用代理的缓存(Leverage proxy caching )
利用浏览器的缓存
概览
在HTTP头部为静态资源设置明确过期日期或最大有效期,这些设置将指导浏览器首先从本地磁盘上(而不是通过网络)加载这些资源。
详情
HTTP/S支持浏览器本地缓存静态资源。一些较新的浏览器(例如IE7,谷歌浏览器Chrome等)使用启发式规则确定多久缓存所有的资源,而不依赖头部明确的缓存设置。其他较老的浏览器可能依赖头部的缓存设置去缓冲区拿取资源;而且有些浏览器可能不会缓存任何通过SSL发送的资源。
为了让所有浏览器获得缓存的好处,我们推荐配置web服务器明确设置缓存头部,并应用给所有可以缓存的静态资源,而不仅仅是小的子设置(例如图片)。可缓存的资源包括JS和CSS文件、图片文件,以及其他二进制对象的文件(例如媒体文件,PDF文件,Flash文件等)。通常,HTML不是静态的,并且也认为是不可缓存的。
HTTP/1.1 提供下列缓存响应头(caching response headers):
Expires
andCache-Control : max-age
(有效期和缓冲控制:最大时限
)。
详细指定资源的“保鲜期”, 即,浏览器能使用该缓存的时间期限。在这个期限内浏览器会直接使用缓存,而不会查看web服务器是否有新版本可用。它们是“强”缓存头,被无条件应用的, 也就是说,一旦它们被设置、而且资源被下载,没有到过期时刻,浏览器不会发出任何GET请求。Last-Modified
andETag
(最后修改和ETag)。详细指定资源的特征,让浏览器确定访问的文件是否相同。Last-Modified
头,通常是一个日期。ETag
头,可以是任何统一定位资源的值(典型为文件版本或内容的哈希值)。Last-Modified
为所有的缓冲资源指定一个 Expires
或 Cache-Control max-age
,并指定一个 Last-Modified
或者 ETag
是很重要的。为所有的资源同时指定 Expires
和 Cache-Control: max-age
,或者同时指定 Last-Modified
和 ETag
推荐
积极的为所有静态资源设置缓存头
- 设置不小于最小的一个月、不大于一年的
Expires
。(与设置Cache-Control: max-age
Expires
更好,因为Expires
能得到更广泛的支持。)不要设置超过一年的Expires
,这样做是违反 RFC(Request For Comments 请求注解)准则的。 如果你知道资源更新的确切时间,可以设置一个较短的过期时间。但是,如果你仅仅知道它“可能很快更新”,并不知道到底什么时候更新,你应当设置一个较长的过期,并使用 URL 指纹(具体描述见下)。积极设置缓存不会“污染”浏览器的缓存:据我们所知,所有浏览器都会依据最近最少使用算法清理自己的缓冲;我们还没有发现有浏览器等到资源过期才清理缓存。 - 为最新更新的资源设置
Last-Modified
日期。如果之前设置的Last-Modified
日期很长,浏览器不会去获取更新的资源。
使用指纹动态启用缓存
对偶尔更新的资源,当服务器更新资源时,可以让服务器告诉浏览器有新的资源可用,让浏览器去缓存它。你可以通过在资源的URL(即:文件路径)嵌入指纹的方式实现这个功能。资源更新时,资源的指纹随之更新,于是资源的 URL也随之更新了。一旦资源的URL更新,浏览器被迫重新获取该资源。指纹允许你设置延迟到未来很久的有效期,甚至可以设置经常更新的资源。当然,这项技术要求所有引用该资源的网页都知道该资源的指纹URL。至于这样做是否弹性欠佳,取决于页面的编码。
为IE浏览器设置正确的 Vary 头
Accept-Encoding
和
User-Agent
在Firefox中避免URL冲突
Firefox 的磁盘缓存哈斯函数会与URL产生碰撞,仅有细微的差别,换句话说只限于8个字符范围的差异(Firefox disk cache hash functions can generate collisions for URLs that differ only slightly, namely only on 8-character boundaries.)。如果几个资源被哈希为相同的键(Key),其中仅有一个资源得到磁盘缓存;剩下的拥有同样键的资源会在Firefox重启的时候重新被获取。因此,只要能确保你的应用程序产生的URL中有超过8个字符不同,使用指纹或者其他程序产生资源文件的URL能最大程度的提高缓存的命中率,避免Firefox哈希冲突。
Firefox 中用 Cache control: public
直接启用 HTTPS 缓存
Cache control: public
例子
下面这个样式表用来显示登录用户的日历。google 日历就在样式文件名中嵌入了一个指纹:calendar/static/fingerprint_key doozercompiled.css,这个指纹键是一个128位的十六进制数。下面是当时的截屏(来自 Page Speed的 Show Resources 面板),这里的指纹是 82b6bc440914c01297b99b4bca641a5d:
对指纹机制,该服务器设置 Expires
头的有效期为一年(原文:The fingerprinting mechanism allows the server to set the Expires
header to exactly one year ahead of the request date)。Last-Modified
头标识文件最后一次修改时间(原文:Last-Modified
header to the date the file was last modified)。Cache-Control: max-age
头是3153600(原文:Cache-Control: max-age
header to 3153600)。每当文件内容发生变化,比如在有效期之前被修改,或者达到最大时限,或者指纹有变化(因此URL也变化了)都会导致客户端重新下载该文件。
附加资源
- 深度体验HTTP缓存,请参见 HTTP/1.1 RFC , 13.2 、14.21 、和14.9.3 节。
- 具体使用Apache缓存,请查阅 Apache Caching Guide 。
利用代理缓存
概览
静态资源可以利用HTTP头部的公开缓存,允许浏览器从附近的代理下载资源,而不必从遥远的原始服务器上下载它们。
细节
除了浏览器缓存,HTTP 还提供代理缓存。代理缓存将静态资源缓存在公共的web代理服务器上,特别是ISP的服务器。也就是说,即使第一次访问你站点的用户也能从缓存中获益:只要其他用户通过这个代理访问过那个静态资源,这个资源对任何其他通过同样代理访问的其他用户来说都是可用的。由于这些地点可能比你的服务器更接近网络用户,所以代理能显著缩减网络延迟。同样的,如果启用代理缓存有效,就是给你免费的网站托管,因此来自代理缓存的响应根本不占用你服务器的带宽。
使用 Cache-control: public
头除了可以声明资源被浏览器缓存外,还可以声明被公共web代理缓存。除了一些例外(下面将描述),你应当为你的web服务器配置这样的头以公开(public
建议
在URL中,不要声明带有静态资源的查询字串
Cache-control: public
不要让代理缓存那些设置了cookies的资源
设置这样的头是为了在多个用户之间有效的公开共享资源,也就是说这些资源的cookies也是可以共享的。然而许多代理并不实际缓存带有cookie头设置的资源。因此最好完全避免这样的风险:设置
Cache-Control
private
)或者让不含cookie 的域(
)提供这些资源
的服务。
注意代理缓存 JS 和 CSS 文件的问题
Content-Encoding
头。结果这些压缩包传到客户端浏览器后不能正确解压。因为这些文件在你的服务器上可能是用
gzipped 格式压缩的,为确保客户端能正确读这些文件,请执行以下任何一个操作:
- 设置
Cache-Control
头为私有的(private
- 设置
Vary: Accept-Encoding