ぶち当たった問題
- Next.jsのImageコンポーネントを使った結果、Cloud Runのメモリをバカ喰いしてました
- 今回は、この原因と解決法を備忘録として残す
先に結論見たい人用
解決法は?
1. 画像最適化を無効化
```javascript:next.config.js
module.exports = {
images: {
unoptimized: true
}
}
```
2. imgタグを使う
<img
src="/images/example.jpg"
width={640}
height={480}
loading="lazy"
decoding="async"
/>
3. CDNを使う
<img
src="https://your-cdn.com/image.jpg?w=800&q=80"
alt="説明"
width={800}
height={600}
loading="lazy"
decoding="async"
/>
- シンプルな実装で確実な動作
- サーバーリソースの消費が少ない
- CDNの最適化機能をダイレクトに活用可能
なんで、 next.jsのImageコンポーネントはメモリをたくさん使うの?
Imageコンポーネントの画像最適化処理(メモリを消費の原因)
- 画像デコード:入力画像をピクセルデータに変換(13MB PNG→約100MB RAM)
- 変換処理:リサイズ/フォーマット変換(Sharp/Squoosh使用)
- エンコード:最適化画像を出力(例:194KB WebP)
-
キャッシュ保存:
.next/cache/images
に書き込み
問題は、変換処理中のメモリ解放遅延
Node.jsのガベージコレクションが処理完了後もメモリを完全に解放しないことがある。
最適化による効果
- フォーマット最適化:画質劣化を最小限に抑えつつファイルサイズを大幅削減
- リサイズ最適化:最適な解像度を動的に選択
- 配信最適化:遅延読み込みによる初期描画速度向上や、プリロードによるLCP改善
Imageコンポーネントは、多くのケースでオーバスペック
サーバーリソースへの影響
- 画像最適化処理がサーバー上で実行され、CPUとメモリを大量に消費する
- コンテナ環境での運用時に
_next/cache/image
へのリクエストが集中し、CPUスパイクやコンテナ停止の原因となる - マルチインスタンス環境での運用が困難
パフォーマンスへの影響
- サーバーサイドでの画像処理により、ページ応答時間が遅延
- 画像のバリアントを複数生成するため、初期ロード時間が増加
- ビルド時間の増加、特に大規模プロジェクトで顕著
解決法は?
1. 画像最適化を無効化
```javascript:next.config.js
module.exports = {
images: {
unoptimized: true
}
}
```
2. imgタグを使う
<img
src="/images/example.jpg"
width={640}
height={480}
loading="lazy"
decoding="async"
/>
3. CDNを使う
<img
src="https://your-cdn.com/image.jpg?w=800&q=80"
alt="説明"
width={800}
height={600}
loading="lazy"
decoding="async"
/>
- シンプルな実装で確実な動作
- サーバーリソースの消費が少ない
- CDNの最適化機能をダイレクトに活用可能
4. 画像サイズを小さくする・WebPけいしきにすr
参考