【问题标题】:Using gzip compression in Sinatra with Ruby在 Sinatra 中使用 gzip 压缩和 Ruby
【发布时间】:2023-03-20 06:57:01
【问题描述】:

注意:我有另一个类似的问题,关于如何使用 Ruby 的 zlib 对数据进行 GZIP 处理,技术上已经回答了这个问题,我觉得我不能开始改进这个问题,因为它已经得到了回答,所以虽然这个问题是相关的它是不一样的......

以下代码(我相信)是对静态 CSS 文件进行 GZIP 压缩并将结果存储在 result 变量中。但是从某种意义上说,我该怎么做:如何将这些数据发送回浏览器,以便将其识别为 GZIP 格式而不是原始文件大小(例如,在检查我的 YSlow 分数时,我希望看到它正确标记我确保我 GZIP 静态资源)。

z = Zlib::Deflate.new(6, 31)
z.deflate(File.read('public/Assets/Styles/build.css'))
z.flush
@result = z.finish # could also of done: result = z.deflate(file, Zlib::FINISH) 
z.close

...需要注意的一点是,在我之前的问题中,受访者澄清说Zlib::Deflate.deflate 不会产生 gzip 编码的数据。它只会产生 zlib 编码的数据,因此我需要使用 Zlib::Deflate.new 和等于 31 的 windowBits 参数来启动 gzip 流。

但是当我运行这段代码时,我实际上并不知道如何处理result 变量及其内容。互联网上(我可以找到)没有关于如何将 GZIP 编码的静态资源(如 JavaScript、CSS、HTML 等)发送到浏览器的信息,这使得页面加载更快。似乎我阅读的每篇 Ruby 文章都是基于使用 Ruby on Rails 的人!!?

非常感谢任何帮助。

【问题讨论】:

    标签: ruby sinatra gzip zlib


    【解决方案1】:

    压缩文件后,您只需返回结果并确保为响应设置标题Content-Encoding: gzip。谷歌有一个不错的小 introduction 用于 gzip 压缩以及您需要注意的事项。以下是您可以在 Sinatra 中执行的操作:

    get '/whatever' do
      headers['Content-Encoding'] = 'gzip'
      StringIO.new.tap do |io|
        gz = Zlib::GzipWriter.new(io)
        begin
          gz.write(File.read('public/Assets/Styles/build.css'))
        ensure
          gz.close
        end
      end.string
    end
    

    不过,最后要提醒一句。您可能应该只为动态创建的内容选择这种方法,或者如果您只想在几个地方使用 gzip 压缩。

    但是,如果您的目标是在启用 gzip 压缩的情况下为您的大部分甚至所有静态资源提供服务,那么依靠您的网络服务器已经支持的内容而不是污染您的代码将是一个更好的解决方案这个细节。您很有可能可以通过一些配置设置启用 gzip 压缩。 Here's 一个例子,说明它是如何为 nginx 完成的。

    另一种选择是使用Rack::Deflater 中间件。

    【讨论】:

    • 感谢您的详细回复和示例代码。我接受了您的 cmets 并改用 Rack::Deflater。从字面上看,我的应用程序文件顶部有一行代码,它起作用了:use Rack::Deflater
    • 投了反对票,因为无论客户端在Accept-Encoding 标头中指定了他们可以接受的内容,这都会提供 gzip 压缩的内容。当然,这是不好的做法,应该避免。
    【解决方案2】:

    只是为了突出显示“Rack::Deflater”作为“答案”->

    如上面评论中所说,只需将压缩放在config.ru中

    use Rack::Deflater
    

    差不多了!

    【讨论】:

    • 这是更好的答案,因为Rack::Deflate 将协商并使用客户端支持的最佳压缩算法
    【解决方案3】:

    我们可以看到用户将压缩网络相关数据,例如css 文件。我想推荐使用brotli。它为此目的进行了大量优化。今天的任何现代网络浏览器都支持它。

    您可以为 ruby​​ 使用 ruby-brs 绑定。

    gem install ruby-brs
    
    require "brs"
    require "sinatra"
    
    get "/" do
      headers["Content-Encoding"] = "br"
      BRS::String.compress File.read("sample.css")
    end
    

    您可以使用流接口代替,它类似于Zlib接口。

    require "brs"
    require "sinatra"
    
    get "/" do
      headers["Content-Encoding"] = "br"
    
      StringIO.new.tap do |io|
        writer = BRS::Stream::Writer.new io
        begin
          writer.write File.read("sample.css")
        ensure
          writer.close
        end
      end
      .string
    end
    
    

    您也可以使用nonblock 方法,请阅读有关ruby-brs 的更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-10
      • 2014-08-21
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 2012-06-17
      相关资源
      最近更新 更多