Edited at

【Rails 6.0】Active Storageの画像変換を高速&省メモリのVipsに換装

個人開発のWebアプリまちかどルートRails 6.0にアップグレードしました。

せっかくなのでRails 6.0の新機能に挑戦したときのメモです。


高速&省メモリのVIPS

Railsの画像アップローダーであるActive Storageですが、公式のドキュメントによると

Rails 6.0では


デフォルトの画像プロセッサはMiniMagickですが、Vipsも使えます。


とあります。

ネットでVipsのことを調べてみると高速かつ省メモリとのこと。

さっそく導入してみようと思いました。


Railsの設定

公式ドキュメントのとおり、下記のGemを導入します。


Gemfile

# gem 'mini_magick' # この行があったらコメントアウトもしくは削除

gem 'image_processing', '~> 1.2' # この行を追加

bundle installしたら、こんどは下記の行を追記します。


config/application.rb

config.active_storage.variant_processor = :vips



開発環境の設定

Railsの設定だけで動くかと思いきや、そうもいかないようです。

じぶんの開発環境のOSはCentOS Linux release 7.6.1810 (Core)つまりCentOS 7なのですが、ここにVipsをインストールしなければいけません。

Vips(libvips)

https://github.com/libvips/libvips

# wget https://github.com/libvips/libvips/releases/download/v8.8.2/vips-8.8.2.tar.gz

# tar zxf vips-8.8.2.tar.gz
# cd vips-8.8.2
# ./configure
# make
# make install

このようにひとつずつコマンドを実行していきます。

そして

# make check

というコマンドでVipsが正常にインストールされたかをしっかり確認します。とくにnoと表示されたライブラリを

# yum install libpng

# yum install libpng-devel

というように追加でインストールしていきます。

そして

# cd vips-8.8.2

# ./configure
# make
# make install
# make check

を行い、make checkのテスト結果に失敗(FAIL)がなくなればインストール成功です。


画像変換のコードを書き換える

従来だと

post.image.variant(resize: "240x300", auto_orient: true, strip: true, quality: 60)

でしたが、Rails 6.0でVipsを使うには

post.image.variant(resize_to_fit: [240,300], autorot: true, saver: { strip: true, quality: 60 })

と書き換えたら動きました。

ちなみにresize_to_fitは画像の縦横比であるアスペクト比を変えないまま設定値以下に縮小するというもの。autorotはスマホでたまにあることですが90度回転して投稿されるのを補正してくれます。stripは画像に含まれる位置情報などのメタデータを削除します。qualityは画像を軽くするための圧縮率です。ほかにもいろいろオプションがあるみたいですね。


Herokuにデプロイ

以上で、ローカルの開発環境でVipsが動作しました。

ところが、本番環境のHerokuにデプロイすると画像が表示されません。

いろいろ調べたところ、下記の設定が必要でした。

heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-apt

heroku buildpacks:add --index 2 https://github.com/brandoncc/heroku-buildpack-vips

Herokuユーザーお馴染みのHeroku CIでこれらのコマンドを実行し、Vipsに必要なライブラリをダウンロード&インストールするためのビルドパックを準備します。

つづいて下記を1行ずつ打ち込んでいきます。

$ cat <<EOF >Aptfile

> libglib2.0-0
> libglib2.0-dev
> libpoppler-glib8
> EOF

あとはいつものようにHerokuにデプロイします。

$ git add -A

$ git commit -m "Add Vips"
$ git push heroku master

じぶんのstackはheroku-18です。stackによってはビルドパックのhttps://github.com/brandoncc/heroku-buildpack-vipsを別のリポジトリに変えたほうがよさそうでした。


あとがき

Qiitaでまとめるようになって約8か月。Rubyでプログラミングを学び始めておよそ1年と2か月が経ちました。いつも思うのですが、こうしてまとめると今回の事も簡単に出来るように見えてしまいます。実際は徹夜でしたけど...。精進します。


2019年9月2日 追記

Herokuにデプロイして丸1日、効果を検証してみました。

その結果、本番環境のHerokuではVipsをいったん無効化しました。一部の画像形式の変換がうまく動かなかったり、メモリ消費量の上昇でスワップが増えてしまったためです。VipsがHerokuで正式にサポートされていないせいでしょうか。ローカルの開発環境ではかなり快速に動作するのですが...。