Reactアプリへのファビコン追加はビルドツールによって異なります。Create React App(CRA)と Vite ではファイルの扱いが違います。 このガイドでは両方を解説し、さらにランタイムでのファビコン切り替え方法 (ダークモードやホワイトラベルアプリに便利)も紹介します。
Create React App(CRA)
CRAは静的ファイルを public/ フォルダに置きます。
favicon.icoをpublic/に置きます。public/index.htmlを開き、<link>タグを確認します (CRAはデフォルトで1つ含めています)。
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
<link rel="manifest" href="%PUBLIC_URL%/site.webmanifest" />%PUBLIC_URL% 変数により、アプリのデプロイ先(サブディレクトリでもルートでも) に関係なくパスが正しく機能します。
Vite + React
Viteは新しいReactアプリのモダンなデフォルトです。ファビコンは public/ に置きますが、 HTMLテンプレートはプロジェクトルートの index.html です (public/ 内ではありません)。
- ファビコンファイルを
public/に置きます。 - ルートの
index.htmlを編集し、<head>にlinkタグを追加します。
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />Viteは SVGファビコン を優先します。type="image/svg+xml" 宣言に 注目してください。favicon.svg を public/ に置き、 先頭にスラッシュを付けて参照します。
必要な全ファイル(ICO、各種PNG、SVG、Apple touch icon、マニフェスト)は、Favicon.one への1回のアップロードで揃います。
ランタイムでのファビコン切り替え
ダークモード対応ファビコンやホワイトラベルアプリでは、小さなフックで ファビコンを動的に変更できます。
import { useEffect } from 'react'
function useFavicon(href: string) {
useEffect(() => {
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement
if (!link) {
link = document.createElement('link')
link.rel = 'icon'
document.head.appendChild(link)
}
link.href = href
}, [href])
}
// Usage
function App() {
useFavicon('/favicon-dark.svg')
return <div>...</div>
}自動切り替えを含む完全なダークモード設定については、ファビコンダークモードガイド をご覧ください。
react-helmetを使う
すでに <head> 管理に react-helmet やreact-helmet-async を使っている場合は、ファビコンを宣言的に定義できます。
<Helmet>
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
</Helmet>Next.js vs React(CRA/Vite)
Next.jsを使っている場合はアプローチが異なります。Next.jsにはタグを自動生成する ファイルベースの規約があります。専用のNext.jsファビコンガイド をご覧ください。
Reactファビコンのよくある問題
- ハードリフレッシュ。 Viteの開発サーバーは強力にキャッシュします。 アイコンが更新されない場合は
npm run devを停止して再起動してください。 - 誤ったフォルダ。 CRAとViteのどちらもファイルは
public/に置き、src/には置きません。 - 先頭のスラッシュの欠落。 パスをルートから解決させるには、
favicon.icoではなく/favicon.icoを使ってください。 - ビルド出力にファイルがない。 ビルド後に
dist/(Vite)やbuild/(CRA)を確認し、ファビコンがコピーされたかチェックしてください。
それでも解決しない場合は、「ファビコンが表示されない」チェックリスト全体をご覧ください。