Rails
sprockets
Zopfli

楽して高圧縮のRails用アセット生成

More than 1 year has passed since last update.


以前の記事

以前にRails on EBの最強アセット展開術という記事(以下で「前記事」と呼びます)を書きましたが、その後状況が変化したので、現在やっていることを改めてメモ書きしてみました。


変わったこと、変えたいこと


Sprocketsによる自動圧縮

一度導入されて外れていたのですが、Sprocketsの3.5.0でgzip圧縮機能が復活しました

ということで、ふつうにgzipをかけるだけなら、前記事のような処理を入れなくても、Sprockets単体で行ってくれるようになりました。asset_syncにつなげれば、自動でgzipを上げてくれます。


Zopfliによる圧縮

ただ、自分はひとひねりを加えていたので、逆に面倒なこととなってしまいました。というのも、生成したアセットに対してZopfliを適用して、単なるgzipよりさらに圧縮したファイルを生成していたからです。とはいえ、そのためだけに自動生成をわざわざ止めるのも、癪にさわるものです。


モンキーパッチしてみた

幸い、RubyからZopfliを呼べるようなgem(miyucy/zopfli)があったので、Sprocketsのgzip圧縮部分をZopfli経由に差し替えてみました。


config/initializers/zopfli_sprockets.rb

# バージョンずれの時は安全上モンキーパッチをやめる

if Sprockets::VERSION == '3.7.0'
require 'zopfli'
module Sprockets
module Utils
class Gzip # :nodoc:
alias zlib_compress compress

# zopfliで圧縮
def compress(target)
mtime = PathUtils.stat(target).mtime
PathUtils.atomic_write("#{target}.gz") do |f|
f.write Zopfli.deflate @source, format: :gzip, mtime: mtime
f.close

File.utime(mtime, mtime, f.path)
end

nil
end

end
end
end
end


念のため、もとの#compressメソッドを別名でバックアップした上で、Zopfli呼び出しに差し替えています。


差し替え結果

予想通り、反映時間は少し伸びて、その反対に圧縮後のファイルは少し縮んでいます。あまり実行頻度が高くなく、所要時間への要求がそこまで高くない&ファイルサイズ縮小のメリットが大きい本番環境では、積極的に取り入れていくのもありかなと思いました。


Sprocketsでの提案

Sprockets側でも、圧縮アルゴリズムを差し替え可能とする提案などがなされていますが、今のところ進展していないようです。