こんにちは、もっと(@mottox2)といいます。普段はフリーランスでウェブやスマホアプリのフロントエンド周りのあれこれをやっています。業務外でも技書博(技術書同人誌博覧会)という技術同人誌即売会の運営メンバーをやっています。

今回は2019年12月に開催された第二回技術書同人誌博覧会でさくらインターネットの運営するクラウド画像変換サービス「ImageFlux」を提供していただいたので、さくらのナレッジで記事を書かせてもらうことになりました。

現状と課題

技書博ウェブについて

技書博のウェブサイトは、一般参加者からは参加するサークルの情報、頒布物の情報、ブックマーク機能が提供されています。一方、サークル参加者からはサークル・頒布物情報を登録できるようなウェブアプリ的な見え方になっています。

ウェブサイトはFirebaseで構築しています。Firebase Hosting、Cloud Functions for Firebaseでウェブサイトの配信、Firestoreにサークル・頒布物・ユーザー情報の保存、Firebase Storageにサークル・頒布物の画像、Firebase Authenticationで認証を行っています。

アクセスの傾向と問題

ウェブサイトを運営する立場からは、できるだけ前日までにサークルや頒布物の確認をしてもらうのがベストなのですが、Google Analyticsを見るとイベント当日がアクセスのピークになっています。また、イベント当日にはPCよりモバイル端末のアクセスが増えることがわかっています。

当日のトラフィックが多く、モバイルが多いことで問題になるのが表示速度です。表示速度を上げるには、様々な要因が考えられますが、一番のネックになっていたのが画像のデータ量です。技書博のウェブサイトにおける画像は、サークル参加者からアップロードされた画像です。本来はアップロード時にリサイズを行うべきですが、優先度が上げることができず対応できないままになっていました。

画像のサイズに向き合う

Firebaseで画像をリサイズするには「Firebase Extention」として提供されているResize Imagesを使うのが一般的だと思います。Resize Imagesは画像のアップロード時に、事前に指定したリサイズを行うFirebaseの拡張機能です。

簡単に導入できるメリットもある一方、何点か気になる箇所がありました。

  • 事前に設定した内容に応じて画像のリサイズが行われ、ディレクトリ等画像の種類に関係なくサイズの設定を行う必要があります。
  • リサイズ後の画像URLを取得するのに必要な情報がWeb UIにあり、コードと管理画面に設定がバラける
  • アップロード後、実際のリサイズ後の画像URLを取得するのが面倒。

Resize Imagesを利用するとFirebaseで完結するメリットはありますが、以上のような点から導入を見送っていました。

ImageFluxの導入

これらの課題を一気に解決するのが『ImageFlux』です。ImageFluxは「クラウド画像変換サービス」と名乗っているさくらインターネットの運営するサービスの一つです。クラウド画像変換サービスというととらえどころがないように感じますが、具体的には画像のリサイズ・クロップ、画像フォーマットの変換等を行い、画像の配信まで含めて面倒を見てくれる便利なサービスです。技書博ではさくらインターネットからツールスポンサーという形でImageFluxの提供をいただくことができたので、ウェブサイトに導入を行いました。

導入方法

導入は非常に簡単でした。会員登録のメール開封からデプロイまで2時間ちょっとという短い時間で行うことができました。

次の2ステップで導入が完了します。それぞれのポイントについて説明します。

  1. 会員登録して管理画面で画像のオリジンを指定
  2. コード中での画像の参照を書き換える

オリジンの指定

ImageFluxでは画像があるオリジンを指定するだけで使い始められます。例えば、example.comというオリジンを指定した際に、example.imageflux.jpといったImageFlux用のオリジンが割り当てられます。その設定でexample.imageflux.jp/sample.jpgというURLにアクセスするとexample.com/sample.jpgという画像が帰ってくる形になります。その際にパラメータを指定することでリサイズなどの処理を行えます。技書博ではFirebase Storageを使っていたので、そのオリジンを指定するだけでオリジンの設定は完了しました。

画像の参照を置き換える

技書博ではもともとFirestoreに画像のURLを保存していました。今回、ImageFluxの導入を行う際にはFirestoreの画像URLをオリジンという扱いにし、Firestore(Firebaseのデータストア)のデータの変更は行わずHTMLをレンダリングする際にURLを書き換える形にしました。
画像を読み込む際にはデータストアに保存されているURLをImageFluxのオリジンに書き換えるメソッドを用意し、そのメソッドだけがImageFluxに関心を向かせるようにしました。具体的には次のようなオリジナルの画像URLを引数にした簡単な関数です。(言語はTypeScriptです)

type ImageOption = {
  width: number
  height: number
  aspect: 'scale' | 'crop'
}

const firebaseOrigin = '' // Firebase Storageのオリジン
const imageFluxOrigin = '' // ImageFluxのオリジン

export const imageUrl = (origin: string, options: Partial): string => {
  let params: Partial<{
    w: number | undefined
    h: number | undefined
    a: number | undefined
    u: number
    f: string
  }> = {
    u: 1, // 出力画像が入力画像より拡大されることを許可しない,
    f: 'webp:auto' // WebPに対応しているブラウザにはWebPで配信する
  }
  params.a = {
    'scale': 0,
    'crop': 2
  }[options.aspect || 'crop']
  if (options.width) params.w = options.width
  if (options.height) params.h = options.height

  const imageParams = Object.keys(params)
    .filter(key => Boolean(params[key as keyof typeof params]))
    .map(key => key + '=' + (params[key as keyof typeof params]))
    .join(',')

  return origin.replace(firebaseOrigin, imageFluxOrigin + '/' + imageParams)
}

技書博のフロントエンドはTypeScriptで書かれているので、パラメータをリーダブルなものにし内部でImageFlux形式のパラメータに書き換えています。外部からの引数はImageFluxに依存しないものにしておき、できるだけSaaSに依存しないように意識しています。この形式にしておけば、SaaSをやめたり、乗り換えたりするタイミングで困ることは少なくなります。また、導入する際も「すぐロールバックできる」という保険を持っておくことで精神的なコストも抑えられます。

コスパを考えた導入

一方、コスパを考えて、ImageFluxを完全に使い尽くすことには力を入れず、基本的な機能を使って効果の高そうな箇所に取り組むことにしました。そこで取り組んだのが次の機能です。

1. 画像のリサイズ

1つめが画像のリサイズです。一般的にユーザーが投稿する画像は(推奨サイズを指定していたとしても)画像サイズがバラバラで、こちらの意図したサイズになることはほとんどありません。実際に表示するサイズにリサイズするだけで大きく容量が削減され、ページの高速化に寄与します。特に画像の枚数が多い一覧系のページでは顕著に高速化を感じられます。

ImageFluxではwとhのパラメータを付与するだけでリサイズが行われます。例えば次の画像は幅504px、高さ710pxに変換して画像を配信してくれます。

https://your-sub-domain.imageflux.jp/w=504,h=710/example/image.png

2. 画像フォーマットの変換

2つめが画像フォーマットです。画像フォーマットというとpngやjpgが思い浮かぶと思いますが、ここで利用するのはWebP(ウェッピー)というフォーマットです。WebPはGoogleが開発している画像フォーマットで、以前からにわかに話題になっていました。話題になっていた当時はChromeでしか対応していなかったのですが、最近はEdgeやFirefoxも対応してSafariでなければ大半のブラウザがサポートするに至っています。(Can I use… WebP?

「うちのサービスはSafariも対応ブラウザだから、WebPは採用できない」と思われる方もいるかもしれません。しかし、ImageFluxにはWebP対応ブラウザはWebPを、非対応ブラウザにはオリジナルのフォーマットで配信するオプションが用意されています。(変換パラメータ – ImageFlux

例えば、次の画像はWebP対応ブラウザにはWebP、それ以外にはpngで配信されているはずです。

効果

ImageFluxを利用した場合の一例を示します。例えば、技書博に参加した、とあるサークルカット画像ではオリジナルが319KBなのですが、リサイズとWebPを併用することで36KBまでデータ量を減らすことに成功しています。

この例ではリサイズの効果は弱く見えますが、想定より大きい画像がアップロードされたときは効果が顕著に見えます。また、WebP化ではかなりのデータ量が削減されていることがわかります。このように、ImageFluxを使えば簡単に画像のデータ量を削減できることが伝わったかと思います。

まとめ

ImageFluxは基本的な機能を使うだけでもページの高速化の役に立つ上に、考えることも少ない素晴らしいサービスです。「画像変換系のサーバーなら自分でも立てられる!」という方もいるとは思いますが、それはおすすめしません。無料トライアルもあるので、一旦試してImageFluxの便利さを体験してもらいたいです。

ページ表示速度が速いことは誰にとってもいいことなので、画像から最適化を始めてみてはいかがでしょうか?