在启用 CloudFlare 的情况下利用浏览器缓存
Posted
技术标签:
【中文标题】在启用 CloudFlare 的情况下利用浏览器缓存【英文标题】:Leveraging browser cache with CloudFlare enabled 【发布时间】:2017-07-20 22:02:30 【问题描述】:这是我的 .htaccess 文件的 sn-p:
# ------------------------------------------------------------------------------
# | ETag removal |
# ------------------------------------------------------------------------------
# Since we're sending far-future expires headers (see below), ETags can
# be removed: http://developer.yahoo.com/performance/rules.html#etags.
# `FileETag None` is not enough for every server.
<IfModule mod_headers.c>
Header unset ETag
<filesMatch "\.(ico|jpe?g|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, public"
</filesMatch>
<filesMatch "\.(x?html?|php)$">
Header set Cache-Control "max-age=600, private, must-revalidate"
</filesMatch>
</IfModule>
FileETag None
# ------------------------------------------------------------------------------
# | Expires headers (for better cache control) |
# ------------------------------------------------------------------------------
# The following expires headers are set pretty far in the future. If you don't
# control versioning with filename-based cache busting, consider lowering the
# cache time for resources like CSS and JS to something like 1 week.
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
# CSS
ExpiresByType text/css "access plus 1 year"
# Data interchange
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
# Favicon (cannot be renamed!)
ExpiresByType image/x-icon "access plus 1 week"
# HTML components (HTCs)
ExpiresByType text/x-component "access plus 1 month"
# HTML
ExpiresByType text/html "access plus 0 seconds"
# javascript
ExpiresByType text/javascript "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
# Manifest files
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Media
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# Web feeds
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
# Web fonts
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
</IfModule>
可以看出,我在适当的语法中有 Cache-Control 和 Expires。然而 Google PageSpeed 工具却说我的 JS 没有利用浏览器缓存。有什么我想补充的吗?
我知道同时包含 Cache-Control 和 Expires 标头不是一个好习惯。所以我删除了 Cache-Control 部分。本地文件(目前不关心第三方外部文件)在通过 Google 运行时仍显示为未缓存。需要缓存的文件是http://www.peppyburro.com/sandboxassets/js/burroinline.js。有问题的 .htaccess 位于文档根目录,即http://www.peppyburro.com/.htaccess。具有上述缓存 sn-p 的 .htaccess 也位于包含 burroinline.js 的 /js 文件夹中。
为了增加混乱,https://www.giftofspeed.com/cache-checker/ 说我的文件正在按预期缓存,而 Google PageSpeed 和 GTMetrix 说它不是。
更新:看起来我的 CDN (CloudFlare) 与缓存问题有关,因为一旦我禁用 CF,缓存就开始工作了。我这么说是因为 Google PageSpeed 在缓存和未缓存之间随机交替,尽管我的 htaccess 没有任何变化!此外,GTMetrix 仍将文件显示为未缓存。这是我的浏览器上的标题:
**General**
Request URL:http://peppyburro.com/sandboxassets/js/burroinline.js
Request Method:GET
Status Code:200 OK (from disk cache)
Remote Address:209.99.16.94:80
**Response Headers**
Accept-Ranges:bytes
Access-Control-Allow-Origin:*
Age:0
Cache-Control:max-age=216000, public
Content-Encoding:gzip
Content-Length:38611
Content-Type:application/javascript
Date:Wed, 01 Mar 2017 16:22:41 GMT
Expires:Thu, 01 Mar 2018 16:22:41 GMT
Last-Modified:Wed, 01 Mar 2017 02:18:53 GMT
Server:Apache Phusion_Passenger/4.0.10 mod_bwlimited/1.4 mod_fcgid/2.3.9
Vary:Accept-Encoding,User-Agent
Via:1.1 varnish-v4
X-Varnish:31524632
这是否意味着文件实际上正在被缓存?如果是这样,如何才能在 Google PageSpeed 和 GTMetrix 中得到一致的反映?我怎样才能使它在启用 CF 的情况下工作?
PS:在共享主机上,我无法访问 httpd.conf。
【问题讨论】:
我建议在查看您遇到问题的单个本地.js
文件之前,先查看您正在调用的所有外部 JavaScript 文件。你有很多,它会对你的网站速度产生影响。见Leverage Browser Caching 3rd Party JS。我也会避免使用 varvy,它不是一个值得信赖的来源,请改用 GTMetrics 和 iwebchk。
【参考方案1】:
编辑:答案最终是 CloudFlare 和 .htaccess 文件之间的冲突。这篇文章的 cmets 讨论了此问题的故障排除和解决方案。
我通过 pingdom 的工具运行此资源以查看请求/响应的样子。
https://tools.pingdom.com/#!/d8QPQx/http://www.peppyburro.com/sandboxassets/js/burroinline.js
实际上并没有被缓存。标头设置为无缓存。
"no-cache" 表示返回的响应不能用于 无需先检查即可满足对同一 URL 的后续请求 如果响应已更改,请与服务器联系。因此,如果一个适当的 验证令牌 (ETag) 存在,无缓存会导致往返 验证缓存的响应,但如果 资源没有改变。
来源:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
服务器的响应是:
Cache-Control public, max-age=216000
因为它是 javascript,所以建议将其延长到一周或更长时间。此外,这里的响应是公开的,而您的设置是
Header set Cache-Control "max-age=216000, private"
年龄是对的,但能见度有差距。
“公共”与“私人”
如果响应被标记为“公共”,那么它可以被缓存,即使 它具有与之关联的 HTTP 身份验证,即使当 响应状态代码通常不可缓存。大多数时候, “public”不是必需的,因为显式缓存信息(例如 "max-age") 表示响应无论如何都是可缓存的。
相比之下,浏览器可以缓存“私人”响应。然而,这些 响应通常针对单个用户,因此中间 缓存不允许缓存它们。例如,用户的浏览器可以 缓存包含私人用户信息的 HTML 页面,但 CDN 不能 缓存页面。
来源:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
我也看到了一些 cloudflare (CDN) 标头,表明它没有被缓存。通常,私人响应适用于敏感内容。我会首先尝试将其设置为公开,但前提是您不关心敏感信息。
如果您担心敏感信息请将此信息保密。
虽然我认为这可能是问题所在,但还有其他几个因素(以 CDN 为中心)也可能导致问题。
Accept-Ranges:bytes
Access-Control-Allow-Origin:*
Age:0
Cache-Control:public, max-age=216000
CF-Cache-Status:MISS
CF-RAY:338d062cb1035a6e-BOS
Connection:Keep-Alive
Content-Type:application/javascript
Date:Wed, 01 Mar 2017 15:07:08 GMT
Expires:Sat, 04 Mar 2017 03:07:08 GMT
Last-Modified:Wed, 01 Mar 2017 02:18:53 GMT
Proxy-Connection:Keep-Alive
Server:cloudflare-nginx
Vary:Accept-Encoding
Via:1.1 varnish-v4
X-Varnish:18615326
这些是来自服务器的响应标头。它们在 CF(cloudflare)缓存中包含一个“MISS”。另外,这里的缓存控制也设置为public。
因此,我认为中间CDN可能会导致缓存问题。
如果您有任何其他信息要提供(例如 CDN/CloudFlare 信息),我很乐意再看一看。
【讨论】:
我将 Cache-Control 更改为“public”,但这并没有解决问题。该文件仍未缓存。我什至尝试完全删除 Cache-Control sn-p,因为我的 htaccess 中已经有 Expires 标头,但问题仍然存在。至于 CDN,是的,我正在使用 CloudFlare,但不确定在此处特别提供哪些信息。 您认为在 js 文件夹中使用带有这些缓存指令的另一个 htaccess 会有所作为吗? 我想说上面提到的额外文件值得一试。我很好奇缓存是否仍然被CF阻止。我会做更多的研究,看看我能发现什么。感谢您测试第一个想法。排除事情总是好的。 另一个想法。您可以将 max-age=216000 更改为与您的 css 相同吗?或者,更好的是,只需在它后面加上 |到您的其余文件类型。例如。 :以上是关于在启用 CloudFlare 的情况下利用浏览器缓存的主要内容,如果未能解决你的问题,请参考以下文章
如何在不增加成本情况下使用Cloudflare Cron 触发器?