实现此目的的一种方法是使用 HTTPLast-Modified
or ETag
标头。在所提供文件的 HTTP 标头中,服务器将发送页面上次修改的日期(在Last-Modified
header),或者代表页面当前状态的随机ID(ETag
), 或两者:
HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Fri, 18 Dec 2015 08:24:52 GMT
ETag: "208f11-52727df9c7751"
Cache-Control: must-revalidate
如果标题Cache-Control
被设定为must-revalidate
,它会导致浏览器缓存该页面以及Last-Modified
and ETag
它收到的标头。在下一个请求时,它将作为If-Modified-Since
and If-None-Match
:
GET / HTTP/1.1
Host: example.com
If-None-Match: "208f11-52727df9c7751"
If-Modified-Since: Fri, 18 Dec 2015 08:24:52 GMT
如果当前ETag
该页面的内容与来自浏览器的页面相匹配,或者如果该页面自浏览器发送之日起没有被修改过,则服务器将不发送该页面,而是发送一个Not Modified
带有空主体的标头:
HTTP/1.1 304 Not Modified
请注意,只有两种机制之一(ETag
or Last-Modified
) 是必需的,它们都独立工作。
这样做的缺点是无论如何都必须发送请求,因此性能优势主要针对包含大量数据的页面,但特别是在高延迟的互联网连接上,页面仍然需要很长时间才能加载。 (但这肯定会减少您的流量。)
阿帕奇自动生成一个ETag http://httpd.apache.org/docs/2.2/mod/core.html#fileetag(使用文件的索引节点号、修改时间和大小)和Last-Modified
静态文件的标头(基于文件的修改时间)。我不了解其他网络服务器,但我认为它会类似。对于动态页面,您可以自己设置标头(例如,将内容的 MD5 和发送为ETag
).
默认情况下,Apache 不发送Cache-Control
标头(默认为Cache-Control: private
)。这个例子.htaccess
文件使 Apache 发送所有的标头.html
files:
<FilesMatch "\.html$">
Header set Cache-Control "must-revalidate"
</FilesMatch>
另一种机制是通过发送使浏览器缓存页面Cache-Control: public
,但要动态改变 URL,例如通过附加文件的修改时间作为查询字符串 (?12345
)。只有当您的页面/文件仅从 Web 应用程序内部链接时,这才真正可能,在这种情况下,您可以动态生成指向它的链接。例如,在 PHP 中你可以这样做:
<script src="script.js?<?php echo filemtime("script.js"); ?>"></script>