这是一个提供图像的网络应用程序。由于相同的请求将始终返回相同的图像,因此我希望访问浏览器尽可能积极地缓存图像。我很想告诉浏览器
这是你的图片。继续并保留它;在接下来的几天里它真的不会改变。不需要回来。真的。我保证。
到目前为止,我确实设定了
缓存控制:公共,最大年龄=86400 最后修改时间:(不久前) 过期时间:(两天后)
当然,如果请求具有适当的
304 not modified
标头,则返回 If-Modified-Since
。
我还能做些什么(或者我应该做些什么不同的事情)来将我的消息传递到浏览器吗?
该应用程序托管在 Google App Engine 上,以防万一。
你可以做得更好。 304 仍然是 HTTP 请求/响应。虽然图像不会再次下载,但延迟可能会很严重。
如果您可以在映像名称中包含版本标识符,则可以将 max-age 设置为 2 年。这样,您就可以防止 304。如果图像发生变化,您可以更新版本标识符,从而更改文件名。这确保浏览器将发出新的请求。
需要对您的项目结构进行一些更改。版本标识符可以是上次更新镜像时的 SVN 修订号,并且可以在构建时自动生成。您还需要更新 html,因此如果您在图像名称和图像路径之间有逻辑映射,您的工作会更容易。
图像很少更新,因此如果您无法自动执行我上面描述的操作,您也可以采用手动方法。诀窍是只添加新图像,而不修改它们。
我不知道它是否会比其他人提供的解决方案更有帮助,但您可以使用 HTML5 离线网络应用程序 设施来更明确地要求浏览器存储本地副本。
缓存头中有一个非常重要的值,您在这里没有提到:
“事后检查=900,事前检查=3600”
阅读有关此主题的这篇文章(并搜索更多内容):
http://www.rdlt.com/cache-control-post-check-pre-check.html
编辑:参考文章的存档版本
尝试 .htaccess 之类的
<ifmodule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifmodule>
<ifmodule mod_deflate.c>
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType application/x-httpd-php .php
AddType application/x-httpd-php .php3
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-javascript
</ifmodule>
<ifmodule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 seconds"
ExpiresByType text/html "access plus 1 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 216000 seconds"
ExpiresByType application/x-javascript "access plus 216000 seconds"
</ifmodule>
<ifmodule mod_headers.c>
<filesMatch "\\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
Header set Cache-Control "max-age=2592000, public"
</filesmatch>
<filesMatch "\\.(css)$">
Header set Cache-Control "max-age=604800, public"
</filesmatch>
<filesMatch "\\.(js)$">
Header set Cache-Control "max-age=216000, private"
</filesmatch>
<filesMatch "\\.(xml|txt)$">
Header set Cache-Control "max-age=216000, public, must-revalidate"
</filesmatch>
<filesMatch "\\.(html|htm|php)$">
Header set Cache-Control "max-age=1, private, must-revalidate"
</filesmatch>
</ifmodule>
您可以为每个图像添加
ETag
表示,然后将其与入站请求上的If-None-Match
标头进行比较(请参阅“为什么我的自定义传递的图像不在浏览器中缓存?”)。当使用首选的 Last-Modified
标头时,这是多余的,而且它只是 304 的另一种表达方式。 (我认为 GAE 自动对静态文件执行此操作,但不确定。)
Gravatar 设置非常旧的
Last-Modified
日期——默认值似乎是“Wed, 11 Jan 1984 08:00:00 GMT”。 5 分钟过期会导致浏览器频繁检查更新的图像。换句话说,我认为他们是在邀请 304,而不是试图说服浏览器只使用本地缓存。他们的标题看起来像这样:
Date: Sat, 20 Mar 2010 07:52:43 GMT
Last-Modified: Wed, 11 Jan 1984 08:00:00 GMT
Expires: Sat, 20 Mar 2010 07:57:43 GMT
Cache-Control: max-age=300
最大的区别是过期时间——你想要两天,他们想要五分钟。因此,如果您希望浏览器仅使用缓存图像 48 小时,请执行您正在做的操作,只需设置
Cache-Control: max-age=172800
(86400 是 24 小时)。
几天的缓存期限非常低。您应该将其设置为一年甚至更长。 当然,当图像实际更改时,这可能会引发问题,但您可以通过向图像添加版本号并更改引用图像的页面以包含新图像的路径来解决该问题。
我在这里写了更多关于 Web 应用程序缓存的内容: http://patchlog.com/web/7-methods-to-cache-web-applications/