コードレビューで見つかった問題を、勉強のためにまとめたものです(修正済み)。
この記事でわかること
- Next.js の
app/icon.pngを置くだけで favicon になる仕組み - そこに大きな画像を置いてしまうと何が起きるか
- どう直したか
- 「便利な convention は、素のまま配る」を意識するための学び
Next.js の icon convention は素通しで配る
Next.js (App Router) には、app/icon.png というファイル名でファイルを置くだけで、それを favicon として配ってくれる convention があります。
具体的には、ビルド時に Next.js が以下の HTML を自動で <head> に挿入してくれます:
<link rel="icon" type="image/png" sizes="2048x2048" href="/icon?[hash]" />ここがポイントで、app/icon.png に 6.7MB の PNG を置けば、ユーザは 6.7MB の PNG を favicon として読みに来ます。
修正前のコード
app/icon.png に置いていたファイルの実体:
$ file frontend/src/app/icon.png
frontend/src/app/icon.png: PNG image data, 2048 x 2048, 8-bit/color RGBA, non-interlaced
$ ls -la frontend/src/app/icon.png
-rw-r--r-- 1 user user 6884468 Apr 30 23:23 frontend/src/app/icon.png2048×2048、約 6.7MB。
これが Next.js の icon convention によって、サイト全ページの <link rel="icon"> から参照される状態になっていた。
なぜ危険か
ふだんブログを読んでいて「favicon が遅い」と感じる場面はほとんどありません。なぜなら 普通の favicon は数 KB ですから。今回のように 6.7MB あると、次のことが起きます。
- 初回訪問のあらゆるページで 6.7MB を追加ダウンロードします
- ランディングページに 1MB の画像を必死で詰めていても、favicon で 6.7MB 配ったらすべて意味がなくなります
- ブラウザのキャッシュに乗るまでの体感が悪化します
- favicon は HTML のパース後に並列で取りに行くため、メインコンテンツの表示はブロックしません
- ただし、回線が細い環境(モバイル / 公共 Wi-Fi)では、メインコンテンツのリソース取得と帯域を奪い合います
- CDN コスト・転送量がじわじわ効いてきます
- 大量に bot が巡回するサイトだと、favicon だけで月のトラフィックが跳ね上がります
- 検索エンジンの Web Vitals 評価が下がります
- Largest Contentful Paint や Interaction to Next Paint といった指標は「画面に映るまでの体感」を測るので、帯域を食われると数値が悪化します
総じて「あらゆるページで配るアセット」の肥大化は、点ではなく面で効く タイプの問題になります。
対策(修正後の方針)
favicon としての役割に必要な解像度・サイズに揃えます。具体的には次のように分割します。
ポイントは:
- favicon は ブラウザに小さく表示される画像 なので、解像度を盛りません
- 「サイトのロゴを大きく見せたい場面(OGP / ヒーロー画像)」と「favicon」を 同じ画像で兼ねません
- 1ファイルに兼用させたくなったときは、いったん「ファイル名は別、画像は同じソースから書き出す」設計に倒します
学びポイント
- 「全ページで読まれるアセット」(favicon、共通フォント、共通 JS)は、点で見ると小さくても面で効きます。サイズの上限を1つの数字で意識します(例: favicon < 30KB、共通 CSS < 100KB)
- 便利な convention(ファイル名で配信される系)ほど、Next.js Image のように暗黙でリサイズしてくれる経路と混同しません
おわりに
「LP のヒーロー画像をどう圧縮するか」みたいな話は、最近は Next.js Image が黙って WebP / AVIF にしてくれるので、ぼんやりしていても致命傷にはなりにくいです。
「便利な convention は、置いたファイルをそのまま素で配る」 ── このタイプのミスは、フレームワークが面倒を見てくれている範囲を勘違いしているとき に起きやすいです。Next.js Image / Server Components / convention based routing といった「賢いレイヤー」と、素通しのレイヤー が同じプロジェクトに同居していることを意識しておくと、似たミスを踏みにくくなります。
この記事は2026年5月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。