Next.jsの next/image
はデフォルトではサーバーサイドで画像最適化するので、 next export
で静的サイトとして利用したい場合、画像最適化を無効化するか、 custom
で指定する必要がある。
9月にリリースされた Next.js 12.3でImage Optimizationを無効化するオプションがStableで利用できるようになったが、画像最適化は行われない……。
ビルド時に画像最適化を行ってくれる next-image-export-optimizer
というライブラリがあり、これを使ってみたのでメモ。
next.jsで画像最適化をする意味
環境
一応一通りセットアップし直してみたコードをGitHubに置いている。*1
- "next": "13.0.6"
- "react": "18.2.0"
- "next-image-export-optimizer": "1.0.1"
セットアップ
基本的にはREADMEを読めばだいたい分かるが、 next.config.js
に設定を追加し、 next/image
を next-image-export-optimizer
に差し替えるだけで動作する。
注意点としては、デフォルトではblur imageが生成され、小さめの画像を読み込む→ぼやけさせるフィルターをかける→読み込みが終わったら一瞬画像が消えたあと、完全な画像に差し替える、という挙動になっている。*2
ここはアプリケーションの要件によると思われるが、 placeholder="empty"
を入れることで上記の挙動を抑制できる。
また、 images.imageSizes
などで画像サイズのリストを指定するが、指定したサイズの数だけ画像が生成されるので、画像枚数が多いとビルド時間がどんどん遅くなる。
当たり前だがハマったポイントとして、 unoptimized: true
になっていた場合は最適化されない。
画像が増えるほどビルドが遅くなる問題
ビルド時に画像最適化するため、画像枚数が多くなるほどビルド時間が増えていき、デプロイ時間がどんどん長くなる。
最適化済みの画像をコミットするという方法もあると思うが、バイナリファイルが増えすぎるのはちょっと嫌な気持ちもあるので、キャッシュすることで回避した。
雑にやっているので、 public/images
以下をまるごとキャッシュしている。チェックアウト後に public/images
を上書きすると本来の画像が使えないので、 actions/checkout
前に行っている。
まとめ
基本的には next/image
のインポートを差し替えれば使えるので、サクッと最適化したいときに良かった。
余談
記事を書いている途中で気付いたが、 next-export-optimize-images
というライブラリもあり、こちらも結構良さそう。
こちらに移行するかも
また、この記事は本業のアドベントカレンダー用に書いた記事だった。