Sådan tilføjer du favicon til dit Next.js-projekt: Komplet implementeringsguide 2025
Favicons er afgørende for moderne webapplikationer og vises i browserfaner, bogmærker, mobilstartskærme og PWA-installationer. Next.js tilbyder flere implementeringsmetoder afhængigt af din routerkonfiguration og funktionskrav.
Denne omfattende guide giver alt, hvad du behøver for at implementere professionelle favicon-systemer i Next.js-projekter, fra grundlæggende opsætning til avancerede dynamiske funktioner.
Det lærer du:
- Next.js 13+ App Router favicon-implementering
- Ældre Pages Router-kompatibilitetsmetoder
- Dynamiske favicon-opdateringer og tematilpasning
- PWA- og multi-enhedsoptimering
- Ydelsesoptimering og fejlfinding
- Virkelige kodeeksempler og bedste praksis
Hurtig start: Grundlæggende favicon-opsætning (5 minutter)
Trin 1: Generér dine favicon-filer
Anbefalet værktøj: Brug RealFaviconGenerator eller Favicon.io for professionelle resultater.
Grundlæggende filstruktur:
public/
├── favicon.ico # Universal kompatibilitet (16x16, 32x32)
├── favicon-16x16.png # Browserfaner (ældre understøttelse)
├── favicon-32x32.png # Højtopløselige browserfaner
├── apple-touch-icon.png # 180x180 (iOS-startskærm)
├── android-chrome-192x192.png # Android-startskærm
├── android-chrome-512x512.png # PWA og højtopløselige skærme
└── site.webmanifest # Progressive Web App-manifest
Trin 2: Hurtig grundlæggende opsætning
Nulkonfigurationsmetode: Placer favicon.ico i public-mappen. Next.js serverer den automatisk på /favicon.ico.
Hurtig verifikation: Besøg http://localhost:3000/favicon.ico for at bekræfte, at filen er tilgængelig.
Next.js 13+ App Router-implementering
Metode 1: Metadata API-konfiguration (anbefalet)
Hvorfor denne metode: Typesikker, indbygget Next.js-understøttelse, automatisk optimering, bedre SEO.
Next.js App Router understøtter filbaseret favicon-konfiguration:
// app/layout.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Next.js App',
description: 'Amazing Next.js application',
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png',
},
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Metode 2: Professionel multi-enheds-konfiguration
Til produktionsklare applikationer med omfattende platformunderstøttelse:
// app/layout.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Next.js App',
description: 'Amazing Next.js application',
// Omfattende favicon-konfiguration
icons: {
// Primære browserikoner
icon: [
{ url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
{ url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
],
// Ældre ICO-understøttelse
shortcut: '/favicon.ico',
// iOS-startskærmsikoner
apple: [
{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' },
],
// Android- og PWA-ikoner
other: [
{
rel: 'icon',
url: '/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
rel: 'icon',
url: '/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png'
},
],
},
// PWA-manifest for app-lignende oplevelse
manifest: '/site.webmanifest',
// Yderligere mobiloptimering
other: {
'theme-color': '#000000',
'msapplication-TileColor': '#000000',
}
}
Metode 3: Dynamisk favicon-generering
Avanceret brug: Dynamiske favicons baseret på brugerkontekst, miljø eller applikationstilstand.
// app/layout.tsx
import { headers } from 'next/headers'
import type { Metadata } from 'next'
export async function generateMetadata(): Promise<Metadata> {
const headersList = headers()
const userAgent = headersList.get('user-agent') || ''
// Miljøbaseret favicon-valg
const isDevelopment = process.env.NODE_ENV === 'development'
const isMobile = /Mobile|Android|iPhone/i.test(userAgent)
// Dynamisk favicon-logik
let faviconPath = '/favicon.ico'
if (isDevelopment) {
faviconPath = '/favicon-dev.ico' // Udviklingsindikator
} else if (isMobile) {
faviconPath = '/favicon-mobile.ico' // Mobiloptimeret version
}
return {
title: 'My Next.js App',
icons: {
icon: faviconPath,
apple: '/apple-touch-icon.png',
},
// Yderligere dynamisk metadata
other: {
'theme-color': isDevelopment ? '#ff6b6b' : '#000000',
}
}
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Ældre Pages Router-implementering (Next.js 12 og ældre)
Metode 1: Komponentniveau-implementering med next/head
Bedst til: Sidespecifikke favicons, eller når du har brug for forskellige favicons til forskellige ruter.
// pages/_app.tsx
import Head from 'next/head'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#000000" />
</Head>
<Component {...pageProps} />
</>
)
}
Metode 2: Global implementering med Custom Document (anbefalet)
Bedst til: Applikationsdækkende favicon-konfiguration, der gælder for alle sider.
// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en">
<Head>
{/* Grundlæggende browserikoner */}
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
{/* Mobilenhedsikoner */}
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png" />
<link rel="icon" type="image/png" sizes="512x512" href="/android-chrome-512x512.png" />
{/* PWA- og platformkonfiguration */}
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#000000" />
<meta name="msapplication-TileColor" content="#000000" />
<meta name="msapplication-config" content="/browserconfig.xml" />
{/* Yderligere SEO- og mobiloptimering */}
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Avancerede implementeringer
Dynamiske favicon-opdateringer
Opret en brugerdefineret hook til dynamiske favicon-opdateringer:
// hooks/useFavicon.ts
import { useEffect } from 'react'
export const useFavicon = (faviconUrl: string) => {
useEffect(() => {
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/x-icon'
link.rel = 'shortcut icon'
link.href = faviconUrl
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}, [faviconUrl])
}
// Brug i komponent
export default function MyComponent() {
const [theme, setTheme] = useState('light')
useFavicon(theme === 'dark' ? '/favicon-dark.ico' : '/favicon-light.ico')
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
)
}
Notifikationsbadge-favicon
Opret et notifikationssystem med favicon-badges:
// components/NotificationFavicon.tsx
import { useEffect, useRef } from 'react'
interface NotificationFaviconProps {
count: number
originalFavicon?: string
}
export const NotificationFavicon: React.FC<NotificationFaviconProps> = ({
count,
originalFavicon = '/favicon-32x32.png'
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 32
canvas.height = 32
const img = new Image()
img.onload = () => {
if (!ctx) return
// Tegn originalt favicon
ctx.drawImage(img, 0, 0, 32, 32)
if (count > 0) {
// Tegn notifikationsbadge
ctx.fillStyle = '#ff4444'
ctx.beginPath()
ctx.arc(24, 8, 8, 0, 2 * Math.PI)
ctx.fill()
// Tegn tællertekst
ctx.fillStyle = 'white'
ctx.font = 'bold 10px Arial'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(count > 9 ? '9+' : count.toString(), 24, 8)
}
// Opdater favicon
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/png'
link.rel = 'shortcut icon'
link.href = canvas.toDataURL()
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}
img.src = originalFavicon
}, [count, originalFavicon])
return null
}
// Brug
export default function App() {
const [notifications, setNotifications] = useState(0)
return (
<>
<NotificationFavicon count={notifications} />
<button onClick={() => setNotifications(notifications + 1)}>
Tilføj notifikation ({notifications})
</button>
</>
)
}
Tema-adaptivt favicon
Implementer favicon der tilpasser sig systemtema:
// components/ThemeAdaptiveFavicon.tsx
import { useEffect, useState } from 'react'
export const ThemeAdaptiveFavicon = () => {
const [isDark, setIsDark] = useState(false)
useEffect(() => {
// Tjek systempræference
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
setIsDark(mediaQuery.matches)
// Lyt efter ændringer
const handleChange = (e: MediaQueryListEvent) => {
setIsDark(e.matches)
}
mediaQuery.addEventListener('change', handleChange)
return () => mediaQuery.removeEventListener('change', handleChange)
}, [])
useEffect(() => {
const faviconUrl = isDark ? '/favicon-dark.ico' : '/favicon-light.ico'
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/x-icon'
link.rel = 'shortcut icon'
link.href = faviconUrl
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}, [isDark])
return null
}
// Brug i _app.tsx eller layout.tsx
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<ThemeAdaptiveFavicon />
<Component {...pageProps} />
</>
)
}
Web Manifest-konfiguration
Opret et komplet web manifest til PWA-understøttelse:
// public/site.webmanifest
{
"name": "My Next.js App",
"short_name": "NextApp",
"description": "Amazing Next.js application",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#000000",
"background_color": "#ffffff",
"display": "standalone",
"start_url": "/",
"scope": "/"
}
Build-time favicon-generering
Automatisér favicon-generering under build:
// scripts/generate-favicons.js
const sharp = require('sharp')
const fs = require('fs')
const sizes = [
{ size: 16, name: 'favicon-16x16.png' },
{ size: 32, name: 'favicon-32x32.png' },
{ size: 180, name: 'apple-touch-icon.png' },
{ size: 192, name: 'android-chrome-192x192.png' },
{ size: 512, name: 'android-chrome-512x512.png' }
]
async function generateFavicons() {
const inputFile = 'assets/logo.png'
for (const { size, name } of sizes) {
await sharp(inputFile)
.resize(size, size)
.png()
.toFile(`public/${name}`)
console.log(`Generated ${name}`)
}
// Generér ICO-fil
await sharp(inputFile)
.resize(32, 32)
.toFile('public/favicon.ico')
console.log('Generated favicon.ico')
}
generateFavicons().catch(console.error)
// package.json
{
"scripts": {
"generate-favicons": "node scripts/generate-favicons.js",
"build": "npm run generate-favicons && next build"
}
}
Almindelige problemer og løsninger
Problem 1: Favicon opdateres ikke under udvikling
Problem: Browseren cacher gammelt favicon under udvikling
Løsning:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/favicon.ico',
headers: [
{
key: 'Cache-Control',
value: process.env.NODE_ENV === 'development'
? 'no-cache, no-store, must-revalidate'
: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
module.exports = nextConfig
Problem 2: Favicon mangler i produktion
Problem: Statiske filer serveres ikke korrekt
Løsning:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return [
{
source: '/favicon.ico',
destination: '/favicon.ico',
},
]
},
}
module.exports = nextConfig
Problem 3: Flere favicon-formater indlæses ikke
Problem: Kompleks favicon-opsætning forårsager konflikter
Løsning: Brug en prioritetsbaseret tilgang:
// components/FaviconManager.tsx
import Head from 'next/head'
export const FaviconManager = () => {
return (
<Head>
{/* Høj prioritet: Moderne browsere */}
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
{/* Medium prioritet: PNG-fallback */}
<link rel="icon" type="image/png" href="/favicon-32x32.png" />
{/* Lav prioritet: Ældre ICO */}
<link rel="shortcut icon" href="/favicon.ico" />
{/* Mobilspecifik */}
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
</Head>
)
}
Test af din favicon-implementering
Udviklingstjekliste
- [ ] Favicon vises i browserfaner
- [ ] Favicon vises i bogmærker
- [ ] Mobil "Føj til startskærm" fungerer
- [ ] PWA-installationsikon er korrekt
- [ ] Mørk/lys tilstand-tilpasning (hvis implementeret)
Professionelle testværktøjer
1. Favicon.im - Hurtig validering
- Hurtig favicon-udtrækning og test
- Kompatibilitetstjek på tværs af platforme
- Identifikation af manglende størrelser
- Bedst til: Hurtig validering og fejlfinding
2. RealFaviconGenerator Checker - Omfattende analyse
- Detaljeret platformspecifik test
- PWA-overensstemmelsesverifikation
- Ydelsesanbefalinger
- Bedst til: Professionelle audits og optimering
3. Browser DevTools - Teknisk fejlsøgning
- Netværksfanen til indlæsningsproblemer
- Konsolfejl for manglende filer
- Applikationsfanen til manifest-inspektion
- Bedst til: Teknisk fejlfinding og ydelsesanalyse
Manuelle testtrin
- Ryd browsercache
- Besøg din side i inkognitotilstand
- Test på forskellige enheder
- Bekræft bogmærkeudseende
- Test "Føj til startskærm"-funktionalitet
Ydelsesoptimering
Filstørrelsesoptimering
# Optimér PNG-filer
pngquant --quality=65-80 --output favicon-optimized.png favicon.png
# Optimér ICO-filer
convert favicon.png -resize 32x32 -colors 256 favicon.ico
HTTP-cachingheadere
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/:path(favicon.ico|.*\\.png)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
module.exports = nextConfig
Komplet implementeringstjekliste
Fase 1: Grundlæggende opsætning
- [ ] Generér favicon-filer med RealFaviconGenerator eller Favicon.io
- [ ] Placer filer i public-mappen med korrekt navngivning
- [ ] Vælg implementeringsmetode (App Router vs Pages Router)
- [ ] Grundlæggende HTML-opsætning med nødvendige link-tags
- [ ] Test grundlæggende funktionalitet på tværs af større browsere
Fase 2: Multi-enhedsoptimering
- [ ] iOS-startskærmsunderstøttelse (180x180 apple-touch-icon)
- [ ] Android-kompatibilitet (192x192 og 512x512 ikoner)
- [ ] PWA manifest-konfiguration for app-lignende oplevelse
- [ ] Windows tile-understøttelse med korrekte meta-tags
- [ ] Temafarveintegration for mobilbrowsere
Fase 3: Avancerede funktioner (valgfrit)
- [ ] Dynamiske favicon-opdateringer med brugerdefinerede hooks
- [ ] Tema-adaptive ikoner til lys/mørk tilstand
- [ ] Notifikationsbadges til realtidsopdateringer
- [ ] Ydelsesoptimering med cachingheadere
- [ ] Build-time generering med automatiserede scripts
Vigtige implementeringsstrategier
Til moderne Next.js-projekter (13+)
Anbefalet: Brug App Router med metadata.icons API for typesikker, optimeret favicon-håndtering.
Til ældre projekter (12 og ældre)
Anbefalet: Implementer i _document.tsx for global dækning med next/head for sidespecifikke behov.
Til dynamiske applikationer
Avanceret: Kombinér statisk opsætning med runtime-opdateringer ved hjælp af brugerdefinerede hooks og canvas-manipulation.
Til PWA-applikationer
Essentielt: Inkludér omfattende manifest-konfiguration med flere ikonstørrelser og korrekte meta-tags.
Afsluttende anbefalinger
Start enkelt: Begynd med grundlæggende ICO + PNG-opsætning, og udvid derefter baseret på behov
Brug professionelle værktøjer: RealFaviconGenerator for omfattende dækning
Test grundigt: Validér på tværs af browsere, enheder, og brug Favicon.im til hurtig test
Optimér ydeevne: Implementér korrekte cachingheadere og komprimer favicon-filer
Planlæg for vækst: Design dit favicon-system til at kunne rumme fremtidige funktioner som notifikationer og tematilpasning
Ved at følge denne omfattende guide vil du skabe et professionelt favicon-system, der forbedrer brugeroplevelsen, styrker brandgenkendelse og fungerer gnidningsfrit på tværs af alle moderne enheder og browsere.
Use favicon.im to quickly check if your favicon is configured correctly. Our free tool ensures your website's favicon displays properly across all browsers and devices.
Free Public Service
Favicon.im is a completely free public service trusted by developers worldwide.