如何在Heroku Cedar上为静态Rack网站启用gzip压缩?

4

在阅读使用Rack在Heroku上创建静态网站文章后,我使用以下config.ru文件在Heroku上创建了一个静态网站:

use Rack::Static,
  :urls => ["/images", "/js", "/css"],
  :root => "public"

run lambda { |env|
  [
    200, 
    {
      'Content-Type'  => 'text/html', 
      'Cache-Control' => 'public, max-age=86400' 
    },
    File.open('public/index.html', File::RDONLY)
  ]
}

当我在 YSlow 上运行结果时,它报告说没有任何文件被 gzip 压缩。我该怎么做才能压缩资产和 public/index.html 文件?
1个回答

10

根据我使用 Sprockets、Sinatra 和 Rack::Deflater以往经验, 我相信只需要再添加一行use Rack::Deflater 就可以实现我想要的效果。

我将 config.ru 改为了以下内容:

use Rack::Static,
  :urls => ["/images", "/js", "/css"],
  :root => "public"
use Rack::Deflater

run lambda # ...same as in the question

我能够验证响应已经被压缩并发送:

$ curl -H 'Accept-Encoding: gzip' http://localhost:9292 | file -
/dev/stdin: gzip compressed data

但不适用于 /css/js/images下的静态资源:

$ curl -H 'Accept-Encoding: gzip' http://localhost:9292/css/bootstrap.min.css | file -
/dev/stdin: ASCII English text, with very long lines

我意识到这是一个标准的中间件堆栈——Rack::Static 拦截 静态文件的调用,从而跳过以下的堆栈!这就是为什么它对于public/index.html有效,但对于资源无效的原因。

下面的config.ru可以正常工作(请注意,现在use Rack::Deflater位于use Rack::Static之前):

use Rack::Deflater
use Rack::Static, 
  :urls => ["/images", "/js", "/css"],
  :root => "public"

run lambda { |env|
  [
    200, 
    {
      'Content-Type'  => 'text/html', 
      'Cache-Control' => 'public, max-age=86400' 
    },
    File.open('public/index.html', File::RDONLY)
  ]
}

已验证:

$ curl -H 'Accept-Encoding: gzip' http://localhost:9292/css/bootstrap.min.css | file -
/dev/stdin: gzip compressed data, from Unix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接