画像処理サービスimgixのAutomatic機能が便利
今回は小ネタです。
マナリンクではimgixという画像処理サービスを使っているのですが、先日とても便利な機能を見つけたので記事にしました。
imgixの概要
できること
imgixを簡単に言うと、「画像にアクセスするURLに規定のクエリパラメータを付与することで、様々な処理済みの画像が得られるサービス」です。
たとえば、以下の画像について考えてみます。この画像のURLはhttps://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png
です。
URLの末尾にサイズを操作するパラメータを付けて、思い切り小さくしてみましょう。
https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png?w=100&h=100&fit=clip
このように、クエリパラメータを末尾に付けてアクセスすると、画像処理後の画像が得られる、というのがimgixの基本思想です。
なにがうれしいか
あくまで元画像はストレージに保有したまま、表示したいページに応じて、最適なサイズの画像を<img>
タグで指定して表示できることです。
そして、それを非常に少ない工数で実装することができます。
本来こういった要件を満たそうと思ったら、画像のアップロードをフックにして、あらかじめ複数サイズの画像を生成してストレージに保有する必要があります。
しかしimgixを利用していると、あくまでその画像を表示したい側がクエリパラメータを末尾に付けるだけで欲しい画像サイズで得ることができるので、ストレージのコストや実装工数を削減できます。
最適なサイズの画像をWeb上で利用することで、パフォーマンスを向上させることができます。
imgixは画像処理を高速で行ってくれる上で、一度処理した画像はCDN上にキャッシュしておいてくれるため、2回目以降のアクセスはリサイズ後の画像のダウンロード時間しか掛からないため非常に高速です。
簡単にcurlコマンドを実行してチェックしてみました。
❯ curl "https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png" -I HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 132238
...中略
X-Served-By: cache-sjc10058-SJC, cache-tyo11970-TYO
X-Cache: MISS, MISS
❯ curl "https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png" -I
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 132238
...中略
X-Served-By: cache-sjc10058-SJC, cache-tyo11957-TYO
X-Cache: MISS, HIT
まったく同じ画像ですが、2回めの実行はより速くレスポンスが返ってきました。また、X-Cache
ヘッダを見るとキャッシュヒットしていることが伺えます。
どうやって使うのか
Amazon S3などのストレージサービスと連携することで、そこに上がっているリソースをimgixのドメイン経由で利用することができます。
マナリンクはAWSを使っていて、かねてから画像はS3にあげているので、S3と連携しました。
もともとS3の前段にCloudFrontを置いていて、assets.manalink.jp
ドメインでアクセスできるようにしていたのですが、このままのURLだと画像処理は噛ますことができません。
https://assets.manalink.jp/images/202112/guest/webeng-bosyu.png
あくまでprod-manalink-images.imgix.net
といったimgixのドメインでアクセスすることで、機能が利用できます。
料金は?
最低月額10ドルから始めることができます。そこから従量課金ですが、マナリンクでは現状ずっと10ドルのままです。imgixがお得だなぁという気持ちと、トラフィックもっと増やしたいなぁという複雑な気持ちになりますw
Automatic機能
ここから本題なのですが、Automaticという機能にようやく気がついたという話をします。
auto=format
というパラメータを付けると、WebP対応ブラウザから開かれた場合はWebPを、そうでない場合は(おそらく)元画像のフォーマットで返してくれます。
実は、fm=webp
というオプションがあって、これを付けることでWebPを得ることができるのは以前から知っていました。
❯ curl "https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png?fm=webp" -I
HTTP/1.1 200 OK
Connection: keep-alive
...
Content-Type: image/webp
...
X-Cache: MISS, MISS
Content-Typeがimage/webp
になっていることが分かると思います。
しかし強制的にWebPを得られるということは、このURLでは一部のブラウザで画像がそもそも開くことができません。
なので僕はつい先日まで、<picture>
を使ってフォールバック可能になるようにマークアップしていました。
しかしauto=format
を使えば、WebP対応しているかしていないかで返ってくる画像がそもそも異なるので、WebP未対応ブラウザのことは考えずに画像を表示できます。
おそらくAccept
ヘッダとUser-Agent
ヘッダを見ることによって、ブラウザの判定をしているものと考えられます(Varyヘッダから推察。ドキュメントのどこかにロジックが書いてあるかもしれませんが見つけられていません)。
❯ curl "https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png?auto=format" -I
HTTP/1.1 200 OK
...
Content-Type: image/png
...
X-Cache: MISS, HIT
Vary: Accept, User-Agent
❯ curl "https://prod-manalink-images.imgix.net/images/202112/guest/webeng-bosyu.png?auto=format" -I -H 'Accept: image/webp'
HTTP/1.1 200 OK
...
Content-Type: image/webp
...
X-Cache: MISS, HIT
Vary: Accept, User-Agent
以上のように、Acceptヘッダによって返ってくるContent-Typeが異なるのは少なくとも確認できました。
同様にauto=compress
というクエリパラメータもあり、こちらは画質などを少し下げながら画像サイズの削減をしてくれます。
これまでフロントエンドでコンポーネントごとにwidth/heightの設定をやってきたのですが、それらに加えてformat/compressを使うことでより画像サイズが削れそうです。
実際に、マナリンク上でのとあるページで2MB以上の画像が複数枚表示されてしまっているページがあったのですが、imgixのホスト名に置換してクエリパラメータをつけるように実装したところ、それぞれ70KB前後にまで抑えられました。
これがユーザーさんにも社内メンバーにも一切の手間なく実現できたのが大きいです。
マナリンクでは以下のように、登録している先生が自由に指導コースを作ることができます。本文中にさまざまなオンライン指導のイメージ画像を挿入いただくことも多く、こういった画像を全部imgixに置換してからブラウザに表示することで、パフォーマンスと自由度の両立ができたと思います。
データベースにはassets.manalink.jp
ドメインのURLでデータを入れつつ、出力時のPresentation層での処理でimgixへの置換やクエリパラメータへの付与を行っているので、ページごとにクオリティ調整もできるし、万が一imgixをやめたいとなったときもリスクが低いです。
まとめ
- imgixはいいぞ
- パフォーマンスは大事だぞ
- 便利なサービスはどんどん使っていきたい
オンライン家庭教師マナリンクを運営するスタートアップNoSchoolのテックブログです。 manalink.jp/ 創業以来年次200%前後で売上成長しつつ、技術面・組織面での課題に日々向き合っています。 カジュアル面談はこちら! forms.gle/fGAk3vDqKv4Dg2MN7
Discussion