イマドキの画像配信方法 画像配信の多様な手法と最適化

一口に「Webに画像を載せる」と言っても、さまざまな方法があります。CodeGridの例を元に、画像の配信方法を考えてみます。

発行

著者 渡辺 由 フロントエンド・エンジニア
イマドキの画像配信方法 シリーズの記事一覧

はじめに

WebサイトやWebアプリケーションでは、ほとんどの場合画像が使われます。メインビジュアルやブログ記事中の写真、アイコン、ロゴなどさまざまですが、画像はHTMLやCSS、JavaScriptといったテキストファイルよりもサイズが大きくなりがちで、パフォーマンスへの影響も比較的大きいものです。

この記事では、パフォーマンスや運用面を考慮した画像の配信方法について整理していきます。

CodeGridの場合を見てみよう

「画像の配信」と言われても、ちょっとイメージが湧きにくいかもしれません。この記事ではCodeGridのWebサイトを例に取り上げます。

といっても、CodeGridが模範的だったり尖った技術だけを使っているというわけではありません。10年以上にわたって運用する中で、「こういうことを実現したい」「こういうサービスができていて便利そう」という改善を繰り返して、いくつかの管理・配信方法を併用しています。たとえば、初期の頃のCodeGridでは、サーバーはHeroku、DBはMongoDBを使っていました。現在ではこのあとのお話でも出てくるように、CDNサービスとヘッドレスCMSを利用に変わり、それに伴い、画像配信方法も変わってきています。

こんなことをしたいからこんな方法を採用している、というCodeGridの例をとおして、画像配信の手札を増やすヒントになれば幸いです。

過去のCodeGridの技術構成

次の記事では、2018年時点でのCodeGridの技術構成などが話されています。ご参考までに。

HTMLと同じ場所にある画像

CodeGridのWebサイトは、https://www.codegrid.net/で公開されています。HTMLやCSS、JavaScriptも、次のように、このドメイン配下から配信されています(一例)。

https://www.codegrid.net/_astro/done.BGxdpg-Y.css

画像の一部はこれらのファイルと同じ場所から配信されています。

たとえばCodeGridとは?というページがあります。このページではいくつか画像が使われていますが、次のようなURLになっています。

https://www.codegrid.net/assets/about/feature_01.svg

これは先ほどのHTMLやCSSと同じドメイン配下にある画像です。CodeGridのサイトのソースコードは、Gitリポジトリで管理・運用していますので、これらの画像もコードと同じリポジトリに含まれており、最終的にはHTMLやCSSファイルと同じサーバーから配信されます。

ロゴやアイコン

ロゴやアイコンなどもインラインSVGとしてHTMLに埋め込まれているので、これらも広義では「HTMLと同じ場所からの配信」と言えるかもしれません。

CMSサービスから配信される画像

次に、著者のページを見てみると、ここには著者のアイコン画像があります。URLは次のようになっています。

https://media.graphassets.com/resize=w:160/compress/zHmECCHkRMhdWmNwbsBz

一見CodeGridのURLとはまったく関連なさそうに見えます。

これは、CodeGridで利用しているHygraphというヘッドレスCMSサービスから配信されている画像です。CMSサービスにアップロードしておいた画像を表示しているわけです。

CDNサービスから配信される画像

記事中でも画像が使われることがあります。図版やスクリーンショットです。こういった画像は、たとえば次のようなURLになっています。

https://cdn.codegrid.net/2025-screen-and-element-positions/assets/img/positions.png

HTMLやCSSファイルは www.codegrid.netでしたが、こちらはwwwではなくcdnというサブドメインからの配信です。これは、AWS(Amazon Web Services)が提供するサービスを利用して保存・配信しているものです。

画像専用のCDNサービスから配信される画像

CodeGridのサイト内で表示する画像ではありませんが、各記事ページのOGP画像の配信にはImgixという画像専用のCDNサービスを利用しています。

それぞれの配信方法の特徴と利点

CodeGridの例を見てきましたが、それぞれの配信方法について、具体的にその特徴や利点を考えてみましょう。

HTMLと同じ場所から

Gitリポジトリに画像も含めて管理していたり、ビルドしたサイトのリソースをそのままサーバーへアップロードする場合はこのようになるでしょう。管理や、ローカルでのプレビューも容易です。

パフォーマンスを考慮して画像の最適化をしたり、同じ画像でもPC用、スマートフォン用など複数サイズを用意したい、などの場合には、フレームワークの機能などを利用して、ローカルで適宜処理を行う必要があります。ただ、CodeGridの例では、画像はSVGなのでスケーラブルですし、頻繁に更新を行うページでもないため、Gitリポジトリに画像も含めて管理するこの方法が合っていそうです。

Gitリポジトリで管理するとコンテンツと画像の更新履歴をまとめて追えるので、運用しやすいでしょう。

CMSサービスから

次に、CMSサービスにアップロードした画像を配信する場合です。CMSサービスの多くは、画像に関する便利な機能を備えています。たとえば画像を1枚アップロードしておけば、URLのパラメータを変更するだけで、好きなサイズや圧縮率で配信でき、画面幅に応じたサイズの画像を取得・表示する、などの運用も可能です。

CodeGridの場合は、著者のアイコンをヘッドレスCMSサービスのHygraphから配信しています。著者の画像は、記事一覧ページや記事のページでも使われており、表示される場所によってサイズもさまざまです。また、アイコン画像はあくまで目印なので、画像内のテキストが読めるように……といった必要もありません。

そのため、著者のアイコン画像は、Hygraphの機能を利用して、画像の圧縮やサイズ指定してリクエストしています。前章で取り上げたアイコン画像のURLは次のとおりでした。

https://media.graphassets.com/resize=w:160/compress/zHmECCHkRMhdWmNwbsBz

よく見てみるとcompressresize=w:160といった単語が含まれており、これによって「圧縮して、横幅160pxにリサイズした画像」を取得していることがわかります。

画面幅による画像の出し分け

CMSの画像機能を利用すれば、CMSには大きな画像を1枚アップロードしておくだけで、画面幅に応じて画像を使い分けられます。スマートフォンなど画面の小さなデバイスからのアクセスでは、必要以上に大きな画像を配信せずに済むので、パフォーマンスの向上につながります。 具体的には、picture要素やsrcset属性を使うことになるでしょう。以下の記事を参考にしてみてください。

画像専用のCDNサービスから

画像専用のCDNサービスというのは、ImgixCloudinaryがあります。最近では、CloudflareからもCloudflare Imagesというサービスが提供されています。

これらのサービスでは、Web上の管理画面やAPIから画像をアップロードしておくと、先ほどのHygraphの例のように、パラメーター付きのURLで好みのサイズや圧縮率の画像を取得できるようになります。実は多くのヘッドレスCMSも、裏側ではこれらのサービスを利用しているので、間接的には同じものと言えるかもしれません。Hygraphでは好みのサービスと連携ができますし、PrismicやmicroCMSはImgixと連携しています。

Imgixと連携したヘッドレスCMSサービス

ヘッドレスCMSのPrismic CMSやmicroCMSについては、CodeGridでも下記のシリーズで取り上げています。

CodeGridでOGP画像をImgixから配信しているのは、パフォーマンス上の理由もありますが、画像の加工や文字を挿入するなどの機能が利用できる点も大きいです。

OGP画像には記事のタイトルを入れたいですし、記事のカテゴリーごとに背景色も変化させています。そのためには記事ごとに画像を作らないといけないところですが、Imgixを利用すれば、URLに入れたい文字を指定するだけで、画像の上にテキストを重ねられます。CodeGridではベースの画像を1枚だけ用意しておき、背景色や文字のURLパラメータを自動で生成する仕組みを実現できています。

実際のOGP画像のURLは、ある記事では以下のようになっています。

https://codegrid.imgix.net/image.png?ixlib=js-3.8.0&w=1200&h=630&mark=https%3A%2F%2Fcodegrid.imgix.net%2F~text%3Fixlib%3Djs-3.8.0%26w%3D1000%26txt%3D%25E3%2583%2596%25E3%2583%25A9%25E3%2582%25A6%25E3%2582%25B6%25E3%2583%25BC%25E3%2581%25AE%25E5%25AE%259F%25E8%25A3%2585%25E6%2583%2585%25E5%25A0%25B1%25E3%2582%2592%25E7%259F%25A5%25E3%2582%258B%26txt-fit%3Dmax%26txt-size%3D57%26txt-font%3DHiragino%2520Sans%2520W5%26txt-color%3Dfff&mark-x=90&mark-y=195&blend=%233E8D21&blend-mode=overlay&txt=%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%BC%E3%81%AE%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E6%83%85%E5%A0%B1%E3%81%AE%E6%B4%BB%E7%94%A82025%20%7C%20%E5%89%8D%E7%B7%A8&txt-align=top%2Cleft&txt-font=Hiragino%20Sans%20W5&txt-size=30&txt-pad=100&txt-color=fff

日本語がエンコードされていて読み解きにくいですが、画像に挿入したい記事のタイトルやフォントサイズ、色などの指定が含まれています。

このOGP画像の例のように画像にさまざまな加工したい場合は、こういった画像専用のサービスの利用を検討しても良いかもしれません。Webブラウザからアクセスできる管理画面も提供されているので、多くの画像を扱うサイトや、非エンジニアが画像を扱う場合にも便利です。Cloudinaryにいたっては、画像だけでなく動画の編集機能まで備えており、用途によっては画像編集ソフトの出番がないのでは、と思うほどです。

画像専用CDNサービスの例

以下のシリーズにて、OGP画像の生成や、Cloudinaryの機能について具体的に取り上げています。

汎用のCDNサービスから

最後に、Amazon CloudFrontやCloudflare CDNなど、汎用のCDNサービスからの配信です。画像専用のサービスではないので、管理画面やURLのパラメータで画像の加工ができたりはしませんが、CDNが備えるキャッシュ機能やユーザーの最寄りの拠点から配信されるなどの、パフォーマンス面でのメリットがあります。

CodeGridの記事中で扱う画像は、サイズや内容もさまざまですし、記事中の説明に合わせて、フォーマットを限定したりや敢えて非圧縮のままで画像を掲載したいこともあります。そこで、手元の環境で必要に応じて画像の最適化などを行ってからAWS S3へ配置、そのままCloudFront経由で配信するようになっています。

S3+CloudFrontの選択

S3+CloudFrontというAWSサービスを採用しているのは、採用当時の事情によるものです。執筆時点のCodeGridはCloudflareのサービスでホスティングしていますので、いずれCloudflare R2+Cloudflare CDNへの移行もあるかもしれません。

画像自体の最適化

さて、画像のサイズや圧縮についても少し具体的に見てみます。なるべく画像のサイズを小さくして配信できればサイトのパフォーマンス向上になりますが、ユーザーの環境により表示できない、画質が悪く見える、などの問題が起きるのも困ります。また、複数のサイズやフォーマットの画像を用意するのは、管理・配信方法によっては負担も大きくなります。

専用サービスを利用する場合

上で紹介したような、ImgixやCloudinaryなどの画像専用のCDNサービスや、あるいはHygraphやPrismic、microCMSなどのCMSサービスを利用する場合は、画像の最適化やサイズ変更などの機能が備わっているので、手元での画像の最適化は不要になります。アップロードだけしておけば、使う場面に応じたサイズや解像度を指定すれば良いです。こういったサービスは、画像のフォーマットについても自動で変換してくれるものもあります。

たとえば、JPEG画像をアップロードしておいたら、アクセス元のブラウザの対応状況などを加味して、WebPやAVIFなどの新しいフォーマットで配信してくれます。新しいフォーマットは、画質を保ちながら、ファイル容量を小さくできるケースが多く、Webサイトのパフォーマンス向上につながります。

WebPやAVIF

フォーマットごとの特性や画像との相性については、以下の記事が参考になります。

対応状況に応じて……

ブラウザは、リクエスト時にHTTPヘッダーとしてAccept送信します。これをヒントに、サービス側で最適なフォーマットを選択して配信しているのです。ブラウザの開発者ツールで確認できますので、見てみるとおもしろいかもしれません。ブラウザやOSによる差異もあります。

以下は同じ画像に対しての、ブラウザごとのAcceptリクエストヘッダーの例です。

# Chrome
image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8

# Safari
image/webp,image/avif,image/jxl,image/heic,image/heic-sequence,video/*;q=0.8,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5

# Firefox
image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5

# Edge
image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8

受け入れ可能な画像フォーマットの一覧や、優先度などの情報が含まれています。ブラウザにお任せしておけば通常は何も問題ありませんが、詳しく読み解きたい方は、MDNのドキュメントを参照ください。

手元での最適化

画像専用のサービスは強力ですが、そのサービスへの依存も発生しますし、場合によっては費用もかかります。そこまでは必要ないというプロジェクトや、画像もあるでしょう。そういった場合は、手元での最適化を行うことになります。

圧縮ソフトやサービスを使って、手動で画像を作っても良いですが、採用するWebフレームワークによっては、ビルド時に画像の最適化処理を挟むこともできます。たとえばAstroであれば、<Image>コンポーネントや<Picture>コンポーネントが用意されており、出し分けたいサイズやフォーマットを記述しておくと、ビルド時に必要な画像を生成し、それに応じたHTMLを出力してくれます。

まとめ

画像の配信方法について、CodeGridの例をベースに考察してきました。Webサイトの特性や、扱う画像の数、ホスティング環境などに影響される部分も多いもので、「こうすれば良い」という唯一の答えはありませんが、管理・運用がしやすく、かつパフォーマンスを向上させるヒントになっていれば幸いです。