ブラウザのキャッシュをクリアして、何度もリロードしたのに、faviconが真っ白なまま…。こんな経験ありませんか?「キャッシュを消してもfaviconが表示されない」という問題に直面したとき、多くの人がブラウザのせいにしますが、本当の原因はサーバー側にあることが多いんです。
先週、某クライアントのステージング環境でまさにこの問題に3時間もハマりました。Chromeのfaviconキャッシュを消したり、PCを再起動したり、いろいろ試したけど解決しない。結局のところ、ブラウザのキャッシュ問題ではなかったんです。
この記事では、最短で解決する方法と、再発防止のためにチェックすべき根本原因を解説します。
即効解決策:ブラウザキャッシュを完全にバイパスする
ブラウザが新しいfaviconを読み込んでくれない場合、強制的にユニークなリクエストを送る必要があります。具体的には、faviconのパスにクエリ文字列を付与します。これでブラウザは「別のファイルだ」と認識して再取得してくれます。
HTMLの<link>タグにバージョンパラメータを追加してみましょう:
<link rel='icon' href='/favicon.ico?v=20260115' type='image/x-icon'>faviconを更新するたびに、このバージョン番号を変更してください。ユーザーにキャッシュクリアを促すことなく、確実にfaviconを更新できる最もシンプルで確実な方法です。長期的な運用戦略について詳しく知りたい方は、favicon cache busting best practicesのガイドを参考にしてみてください。
キャッシュクリアが効かない本当の理由
ブラウザというのは意外と頑固です。キャッシュをクリアしたとき、削除されるのはHTTPキャッシュだけ。faviconは通常、標準のキャッシュクリアでは消えない別の永続的なデータベースに保存されています。
知られていないSQLite faviconデータベースの存在
ChromeやFirefoxは、favicon専用のSQLiteデータベースを保持しています。このデータベースはブラウザ履歴やブックマークと紐付いているため、通常のキャッシュクリアでは削除されません。ブラウザが「faviconのURLが変わっていない」と判断すると、新しく取得しに行かないんです。
これが、どれだけキャッシュを消してもfaviconが更新されない理由です。ブラウザはハードコードされたURLを確認し、SQLiteデータベースと照合し、一致すれば古いファイルを表示し続けます。
Service Workerによる傍受
PWAを開発している場合、Service WorkerがCache APIから古いfaviconを直接配信している可能性があります。ブラウザのキャッシュをクリアしても、Service Workerのキャッシュには影響しません。
この問題を解決するには、DevToolsでService Workerを登録解除する(Application > Service Workers > Unregister)か、Service Workerファイルを更新して古いfaviconのキャッシュエントリを削除する必要があります。
根本原因:サーバー側で確認すべきこと
クエリ文字列の手法でも解決しない場合、サーバー側でリクエストをブロックしたり、誤ったルーティングをしている可能性があります。現場でよく見る3つのサーバー側の問題を紹介します。
1. CDNの過剰なエッジキャッシュ
CDNが古いバージョンのファイルをグローバルに配信しているかもしれません。CloudflareやVercelなどのCDNは、デフォルトでfavicon.icoのような静的アセットを長期間キャッシュすることがあります。
CDNのダッシュボードにログインし、faviconファイルのキャッシュを手動でパージする必要があります。または、アイコンファイルのTTL(Time to Live)を短く設定することを検討してください。
2. MIME Typeの宣言漏れ
サーバーがファイルの種類をブラウザに正しく伝えていないと、モダンブラウザはそのファイルを拒否します。NginxやApacheの設定で.icoファイルがapplication/octet-streamとして配信されているケースをよく見かけます。Chromeはこれを黙って無視します。
Nginxの設定に正しいMIME Typeが含まれていることを確認してください:
types {
image/x-icon ico;
image/svg+xml svg;
}3.厳格すぎるCORSポリシー
faviconをサブドメインや専用の静的アセットバケットでホストしている場合、CORS(Cross-Origin Resource Sharing)ポリシーがブロックしている可能性があります。レスポンスに適切なAccess-Control-Allow-Originヘッダーがないと、ブラウザはfaviconをレンダリングしません。
この点については、GitHubが完璧な実装をしています。GitHubはSVG faviconを別のCDNドメインでホストしつつ、CORSヘッダーでメインドメインからの取得を許可しています。大手ブランドがどのように対応しているか参考にしたい場合は、GitHubのタブアイコンのネットワークリクエストを確認してみてください。セキュリティ警告を出さずにアイコンを瞬時に読み込むために、適切なヘッダーが設定されています。
2026年にこの悩みをなくす方法
手動でのキャッシュクリアに頼るのはやめましょう。それは終わりのない戦いです。古いfaviconが表示される状況を構造的に防ぐデプロイ戦略が必要です。
- ファイルに必ずバージョンを付ける: ファイル名を
favicon-20260115.icoに変更するか、前述のクエリ文字列の手法を使いましょう。 - Web Manifestも更新する:
manifest.jsonを使用している場合は、そこに記載されているアイコンパスのバージョンも変更してください。ブラウザはHTMLとは独立してmanifestを読み込みます。 - デプロイ時にCDNをパージする: CI/CDパイプラインに、ビルド成功後に自動的にfaviconキャッシュをパージするステップを追加しましょう。
また、本番環境にデプロイする前に設定を検証することも重要です。Mzu favicondlなどのツールを使って、サーバーが正しいヘッダーとファイルタイプを返しているか確認しましょう。
推測をやめて検証を始めよう
キャッシュを消してもfaviconが表示されない問題は、ブラウザのバグだと思い込みがちですが、実際はブラウザがサーバーや隠されたSQLiteデータベースからの古い指示に従っているだけです。
クエリ文字列を付与して強制的にダウンロードさせ、Service Workerを確認し、CDNやMIME Typeを検証しましょう。アイコンが表示されない問題の一般的なトラブルシューティングについては、favicon not showingの包括的なガイドも参考にしてください。
もし推測なしに全プラットフォームでのアイコン設定を検証したいなら、Mzu favicondlにURLを入力してみてください。ユーザーに実際に何が表示されているかを正確に確認できます。