【问题标题】:Nginx Rails/Passenger is not serving gzipped asset filesNginx Rails/Passenger 不提供压缩后的资产文件
【发布时间】:2017-07-13 08:15:58
【问题描述】:

Nginx 1.10.1 Rails 5.0.1。资产管道正在制作 css 和 js 文件的压缩版本和本机版本,但只有未压缩的版本才会提供给浏览器。我可以在 public/assets 中看到这两个版本,我可以使用 curl 通过将“.gz”附加到传递给我的 css/js 资产 url 来检索压缩版本。

我使用的是 CDN (AWS CloudFront),但在没有 CDN 的情况下进行了测试,无论如何它仍应将我指向压缩版本,对吗?

nginx 有--with-http_gzip_static_module。以this answer 为指导,我的 nginx 配置(已编辑)具有:

http {
    server {
        listen       80;
        server_name  idoimaging.com www.idoimaging.com;
        return 301 https://$server_name$request_uri;
    }

    server {
        listen 443 ssl;
        server_name  idoimaging.com www.idoimaging.com;
        root /var/www/idoimaging/current/public;
        location ~ ^/(assets)/ {
            gzip_static on;
        }
    }
}

我还尝试将/assets/ 作为location 中的正则表达式。在我的production.rb

# Have also tried setting this to false
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.middleware.insert_before(Rack::Sendfile, Rack::Deflater)
config.assets.compress = true
config.assets.js_compressor = Uglifier.new(mangle: false)

我正在使用禁用缓存的 Chrome 进行测试,也是为了提高 curl https://idoimaging.com | grep assets 的速度,我认为它应该与浏览器具有相同的行为?

我不知道为什么 nginx 不会在它们存在时提供 gzip 的 js/css 资产文件。

编辑:我还看到this guide 采用另一种方法:使用 Rails 作为静态资产服务器而不是 nginx。这会是更好的方法吗?

【问题讨论】:

    标签: ruby-on-rails nginx


    【解决方案1】:

    鉴于 Rails 正在生成 gzip 压缩的资产,我们可以确信问题仅在于 nginx。所以让我们专注于那里!

    我相信 Nginx 在提供静态资源方面比 Rails 更快,所以无论如何我都不会将它用作静态资源服务器。

    现在查看您提供的 URL (https://idoimaging.com),您的服务器似乎正在提供 gzip 文件。所以问题出在你的测试方法上(假设这是正确的 URL,并且自这篇文章以来你没有更改服务器配置)。

    您的curl 命令不包含Accept-Encoding: gzip 标头,它告诉服务器您的客户端能够处理压缩文件。没有它,Nginx 将提供未压缩的版本。您可以在this gist 中看到命令和输出的差异。区别在于Content-LengthContent-Encoding 响应标头。

    如果您看到不同的东西,请告诉我!

    编辑 1

    这很奇怪,CloudFront 似乎为您的 CSS 和 JS 缓存了重定向。

    richardseviora:Richards-MacBook-Pro@~> curl "https://cdn.idoimaging.com/assets/application-0cd41e63d35c1e5a7ab76ded23fbaf2ef1d1b786144134a80a1dfa9c765cff0d.css" -I -H "accept-encoding: gzip"
    HTTP/1.1 301 Moved Permanently
    Content-Type: text/html
    Content-Length: 185
    Connection: keep-alive
    Server: nginx/1.10.1
    Date: Thu, 23 Feb 2017 03:30:49 GMT
    Location: https://idoimaging.com/assets/application-0cd41e63d35c1e5a7ab76ded23fbaf2ef1d1b786144134a80a1dfa9c765cff0d.css
    Age: 942
    X-Cache: Hit from cloudfront
    Via: 1.1 d8b73f8fefd106d5c95f11977e132c46.cloudfront.net (CloudFront)
    X-Amz-Cf-Id: ao8PwibmSj1JhmfbmuNfC2gYi9x-RTcCrJDAqLWAUIyOjP_3qYTGQA==
    
    
    # It should look like this instead.
    richardseviora:Richards-MacBook-Pro@~> curl -I -H "accept-encoding: gzip" "http://cdn.sweatrecord.com/assets/application-b932da0ddcf53d3650da5135b083224e863b349c784f3d1e3ca992b36ce3e31d.css"
    HTTP/1.1 200 OK
    Content-Type: text/css
    Connection: keep-alive
    Accept-Ranges: bytes
    Content-Encoding: gzip
    Date: Thu, 23 Feb 2017 03:50:13 GMT
    Last-Modified: Mon, 30 Jan 2017 16:29:44 GMT
    Server: Apache
    Vary: Accept-Encoding,Origin
    X-Cache: Miss from cloudfront
    Via: 1.1 8b5947aba7280333032d4dcdd80b3489.cloudfront.net (CloudFront)
    X-Amz-Cf-Id: FN9FyKl0RCpNTTqBwb0WyQhbDd-rEyyQ05eCtaFCD8YaH_FtjG7Q8Q==
    

    这是 Nginx 问题,但我不确定具体在哪里,因为 CloudFront 会cache 301s

    【讨论】:

    • 我仍然没有看到 .gz 文件。我刚刚修改了我的本地 js 和 css 文件,并部署了(Capistrano)。在服务器上,我看到了新的 cs/js 文件,以 zip 和 unzip 形式出现。网络中的 Chrome 仅针对第一项 (idoimaging.com) 显示 Content-Encoding: gzip。 css 和 js 文件都有它们的本机名称,并且在响应标头中没有这个 gzip。两者都是来自 CloudFront 的 301,因为它们是新的,所以这来自服务器。同样在 Sources 下,两个文件都显示本机名称。还是 Chrome 会默默地解压它们?
    • 奇数。真的很奇怪。我已经根据我目前的观察修改了我的答案。
    • 知道了。我天真地使用文件名而不是 Content-Encoding 响应标头,我现在看到了。我一直在想寻找一个“.gz”后缀。我正在查看 301 标头,而不是下一行的实际文件。感谢您提供的信息丰富且耐心的回复。