2

在用sprockets 替换webpacker 的 Rails6 应用程序中,我没有设法让 sprockets 使我的浏览器缓存字体。编辑:我的浏览器确实缓存了字体,但谷歌抱怨并且 curl 显示了应用程序的响应方式(与304不同,见下文)。

更新

似乎304只有当您告诉服务器(通过If-Modified-Since-headers)您确切知道最后修改的版本时才会返回 a 。虽然我的 Mozilla 开发资源并没有说明这显然应该是这种情况(而且我没有阅读 RFC 的心情),但它可能是有道理的:

  • 您的服务器在 2020 年 1 月 1 日为资产提供服务(为简单起见,批准日期)
  • 浏览器访问您并将资产与日期一起存储
  • 第二天同一浏览器重新访问,向服务器询问资产并告诉它最后一个已知日期(2020-01-01通过If-Modified-Since-header)
    • 服务器回答304:你已经知道这些东西了
  • 第二天发生错误,服务器提供开发资产
  • 浏览器重新访问,获取新的(但错误的资产,Last modified日期为 2020-01-03)并将其存储在该日期旁边
  • 服务器管理员删除了错误的开发资产
  • 第二天,浏览器访问并告诉服务器“我知道昨天的事情”
    • 服务器告诉浏览器:不,忘记了,正确的有效载荷是这个,这是时间戳:2020-01-01。

在下面的测试中,我使用If-Modified-Since了与最后一个(生产)资产时间戳不对应的标题。感谢@bliof 帮助解决这个问题。

因为我的最终目标是让谷歌的速度洞察力快乐(现在我知道如果所有玩家都表现良好,这个 304- 响应有效)我将遵循 Rails 5+ 路径config.public_file_server.headershttps://blog.bigbinary.com/2015/10 /31/rails-5-allows-setting-custom-http-headers-for-assets.html)。Rails 指南还指出了您通常如何让您的网络服务器(或 CDN)处理这种情况(https://guides.rubyonrails.org/asset_pipeline.html#in-production),但我的堆栈工作方式有所不同。

原文如下

字体在 eg 中app/assets/fonts/OTF/SourceSansPro-BoldIt.otf并正确放入public/assets/OTF/...fingerprint...(伴随着.gz变体)。它们通过 SCSS font-face 规则引用,指向其中包含相应指纹的文件(使用font-url())。

curling 这些时,我似乎永远不会得到 a HTTP/1.1 304 Not Modified,而是 a200与给定的有效载荷。使用其他(JS,CSS)资产,它可以按预期工作。

我没有修改config/initializers/assets.rb,因为所有子目录和文件都应该已经被拾取(并且assets:precompile输出和内容public/assets显示它有效)。

深入了解https://github.com/rails/sprockets/blob/9909da64595ddcfa1e7ee40ed1d99738961288ec/lib/sprockets/server.rb#L73的 sprockets 代码似乎表明可能没有正确设置 etag 或类似的东西,但我确实这样做了并没有真正破坏该代码。

据我所知,该应用程序使用非常标准的 nginx 配置与 dokku(基本上是 heroku)一起部署:https ://github.com/dokku/dokku/blob/master/plugins/nginx-vhosts/templates/nginx .conf.sigil。该应用程序为资产本身提供服务(如在 heroku 中)。

我该怎么做才能使 sprockets 添加相关的标头/用 a “正确”响应304?任何想法如何调试该问题?

相关的“调试”部分

对 CSS 的初始请求

curl -v https://...application-3d...c76c3.css \
  -H 'Accept: text/css,*/*;q=0.1'\
  -H 'Accept-Language: en-US,en;q=0.5'\
  --compressed # omitted: ... User-Agent, DNT, ...
# omitted: TLS handshake etc
> GET /assets/application-3d...c76c3.css HTTP/1.1
> Host: #the host
> Accept-Encoding: deflate, gzip
> User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
> Accept: text/css,*/*;q=0.1
> Accept-Language: en-US,en;q=0.5
> Referer: #the host
> DNT: 1
> Connection: keep-alive
> Cookie: #a cookie
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 21 Apr 2020 15:39:47 GMT
< Content-Type: text/css
< Content-Length: 41256
< Connection: keep-alive
< Last-Modified: Mon, 06 Apr 2020 11:59:56 GMT
< Content-Encoding: gzip
< Vary: Accept-Encoding
< 
# payload

后续获取 CSS

(相关部分,其他参数和输出省略)。请注意,会同时发送If-Modified-Since: Mon, 06 Apr 2020 11:59:56 GMT标头。

curl -v 'https://.../assets/application-3d...c76c3.css' \
  -H 'If-Modified-Since: Mon, 06 Apr 2020 11:59:56 GMT'\
  -H 'Cache-Control: max-age=0'
> If-Modified-Since: Mon, 06 Apr 2020 11:59:56 GMT
> Cache-Control: max-age=0
> 
< HTTP/1.1 304 Not Modified
< Server: nginx
< Date: Tue, 21 Apr 2020 15:50:52 GMT
< Connection: keep-alive

(这就是我想要的:A 304 Not Modified

字体资源的初始请求

curl -v 'https://.../assets/WOFF2/TTF/SourceSansPro-Light.ttf-32...d9.woff2' \
  -H 'Accept: application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8'\
  -H 'Accept-Language: en-US,en;q=0.5'\
  --compressed \
  -H 'Referer: https://...assets/application-3d....c76c3.css'
  # ommitted: User Agent, Cookies, ....
> GET /assets/WOFF2/TTF/SourceSansPro-Light.ttf-32...d9.woff2 HTTP/1.1
> Host: #the host
> Accept-Encoding: deflate, gzip
> User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
> Accept: application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8
> Accept-Language: en-US,en;q=0.5
> DNT: 1
> Connection: keep-alive
> Referer: https://.../assets/application-3d...c76c3.css
# cookie etc
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 21 Apr 2020 15:45:34 GMT
< Content-Type: application/font-woff2
< Content-Length: 88732
< Connection: keep-alive
< Last-Modified: Wed, 25 Mar 2020 20:09:14 GMT
< 
# payload

后续获取字体

curl -v 'https://.../assets/WOFF2/TTF/SourceSansPro-Light.ttf-32...ed9.woff2' \
  -H 'Referer: https://.../assets/application-3d...c76c3.css'\
  -H 'If-Modified-Since: Mon, 06 Apr 2020 11:59:56 GMT'
  -H 'Cache-Control: max-age=0'
# ....
> If-Modified-Since: Mon, 06 Apr 2020 11:59:56 GMT
> Cache-Control: max-age=0
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 21 Apr 2020 15:53:46 GMT
< Content-Type: application/font-woff2
< Content-Length: 88732
< Connection: keep-alive
< Last-Modified: Wed, 25 Mar 2020 20:09:14 GMT
# payload

我发现有趣的是,服务器实际上发送了Last-Modified,它在If-Modified-Since之前。我猜聪明的浏览器会在那里停止对话,但我真的很想看到一个表现良好的 304。

4

1 回答 1

1

以下是一些注释/发现:


当您匹配时间戳时,它似乎返回 304。

在您的示例中,如果您使用

-H 'If-Modified-Since: Wed, 25 Mar 2020 20:09:14 GMT'

你会得到HTTP/1.1 304 Not Modified

同样的事情,.css如果你不完全匹配日期,你会得到 200。


我尝试在本地更改 sprocket 以添加一些puts调用并更改 sprocket 本身的默认日志级别,但没有任何反应。

TBO 我不相信 Sprokets::Server#call 会被调用。


我试过 withpuma和 with thin,只有在日期匹配时才返回 304 。


curl --compressed -H 'Cache-Control: max-age=0' -H 'If-Modified-Since: Thu, 23 Apr 2020 21:34:30 GMT' -v http://localhost:3000/assets/OTF/SpaceMeatball-d61519ff17fadd38b57e3698067894c0e75fcb6031ee91034f5f7d6f2daa4d4b.otf

> Cache-Control: max-age=0
> If-Modified-Since: Thu, 23 Apr 2020 21:34:30 GMT
>
< HTTP/1.1 200 OK
< Last-Modified: Thu, 23 Apr 2020 21:34:29 GMT

curl --compressed -H 'Cache-Control: max-age=0' -H 'If-Modified-Since: Thu, 23 Apr 2020 21:34:29 GMT' -v http://localhost:3000/assets/OTF/SpaceMeatball-d61519ff17fadd38b57e3698067894c0e75fcb6031ee91034f5f7d6f2daa4d4b.otf

> Cache-Control: max-age=0
> If-Modified-Since: Thu, 23 Apr 2020 21:34:29 GMT
>
< HTTP/1.1 304 Not Modified

我正在运行这样的轨道:

RAILS_SERVE_STATIC_FILES=1 RAILS_ENV=production ./bin/rails s
or 
RAILS_SERVE_STATIC_FILES=1 RAILS_ENV=production bundle exec thin start

待办事项 - 找到返回响应的确切内容:)

于 2020-04-23T22:33:55.383 回答