マイナビジョブサーチ WebチームのK.Kです。
今回は、Next.jsの画像最適化のお話をしたいと思います。
先日インフラ担当の方からこんな指摘をされました。
「Acceptヘッダーを転送していないから、画像の最適化が活かされていない。」
最初よくわからなくて「?」となったので、これをきっかけにNext.jsの画像最適化について調べてみました。
Next.jsの画像最適化とは?
Next.jsではimgタグ、または、next/imageのImageコンポーネントを使用して画像を描画します。
この内、next/imageを使用すると、画像の最適化を行うことができます。
「リサイズ」「フォーマット変換」などを行うことで、ページ読み込み速度が向上するなどといった恩恵が得られます。
リサイズ
リサイズの機能では、表示するディスプレイの大きさに合わせて、画像のサイズを最適化してくれます。
例えばジョブサーチ上のこの画像、以下のように記載されています。


srcset属性に複数のURLが並んでいることがわかります。
これらが、画面サイズごとの画像のパスを示しています。
PC だと「690 × 398」SPだと「640 × 369」の画像が表示に使用されます。
容量を比べると23KB vs 18KBと、SPの方が小さくなっています。
特にSPは通信環境によってページ表示が遅くなりがちなので、容量が小さくなるのは嬉しいですね!
元画像がもっと大きい場合は、より大きな差になるかと思います。
画面サイズごとの画像のパスは、next/imageを使用すると、自動で生成されます。
これらの中から最適な画像をブラウザ上に表示してくれます。
フォーマット変換
フォーマット変換では、ブラウザが対応している画像フォーマットに合わせて、画像フォーマットを最適化してくれます。
どういったフォーマットに変換するかは設定で変更することができ、デフォルトではWebPに変換される設定になっています。
module.exports = {
images: {
formats: ['image/webp'],
},
}
WebPは、JPEGやPNGより圧縮率の高いフォーマットです。
他にAVIFも指定できますが、こちらはより圧縮率が高い代わりに、エンコードに時間がかかるようです。
さて、ジョブサーチのこちらの画像を取り上げます。

この画像、元はJPEGとして保存されています。
これをジョブサーチ上で開くと、JPEGで表示されます。
WebPじゃないの?
Chromeの最新版だから対応しているはずだけど?
そう、これが冒頭で書いた、今回指摘された内容です。
「ブラウザが対応している画像フォーマットに合わせて」画像フォーマットを最適化
ブラウザが対応している画像フォーマット、これは何で判断しているのでしょうか?
それが、Acceptヘッダーなんです。
↓ Acceptヘッダーとは?
HTTP の Accept リクエストヘッダーは、クライアントが理解できるコンテンツタイプを MIME タイプで伝えます。
実際にChromeでリクエストヘッダーのAcceptを見ると「image/webp」の記載があります。
Next.jsではこの値を見て、WebPで返すかどうかを判断しているわけですね。
公式ドキュメントにも以下の記載がありました。
Good to know:
~ 省略 ~
If you self-host with a Proxy/CDN in front of Next.js, you must configure the Proxy to forward the Accept header.
参照元:https://nextjs.org/docs/app/api-reference/components/image#formats
ジョブサーチでは、Next.jsの動作環境にAcceptヘッダーを転送していなかったため、WebPのブラウザがフォーマットに対応しているか判定できず、そのままのJPEGフォーマットで返していたようです。
それでは、実際にAcceptヘッダーを転送して、フォーマットの変換をするとどうなるのか、検証環境で動作させてみました。
すると、
- 元画像(JPEG, 2000×1333):120KB
- Acceptヘッダーなし(JPEG, 916×611):41KB
- Acceptヘッダーあり(WebP, 916×611):20KB
ということで、画像の容量が半分になりました!(圧縮されすぎでは?)
見た目上は変化がわからないのに、これはすごいですね!
最後に
next/imageで画像の最適化をすることで、ページの読み込みが早くなったり、他にも視覚的な安定性が得られたりといったメリットがあります。
SEOにおいてもメリットがあるので、せっかくNext.jsを使用しているなら、動作しているのかちゃんと確認しないとなと思いました。
参考
https://nextjs.org/docs/app/building-your-application/optimizing/images
https://nextjs.org/docs/app/api-reference/components/image#formats
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Accept
※本記事は2025年02月時点の情報です。