你的 Nuxt 应用已经上线,但浏览器标签页上显示的仍然是默认 favicon。更糟糕的是,市场团队希望在结账页面和管理后台使用不同的图标。硬编码 link 标签并不是长久之计——Nuxt 通过 app.head 配置和 useHead 组合式函数为你提供了编程控制的能力,理解这两者,是让你与框架协作而非对抗的关键。

本指南专注于通过 Nuxt 的 head 配置系统来管理 favicon,而不是我们 Nuxt favicon 指南 中提到的基于文件的元数据方法。如果你需要按页面设置图标、支持暗黑模式切换或运行时替换,head API 正是你所需要的。

前置条件

第一步:通过 app.head 设置默认 favicon

nuxt.config.ts 中的 app.head 属性是全局默认配置。除非页面覆盖,否则这里的内容会被注入到每个页面的 <head> 中。

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      link: [
        { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' },
        { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' },
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
        { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }
      ]
    }
  }
})

将图标文件放在 public/ 目录下,这样 Nuxt 会在根路径下提供它们。根据 Nuxt SEO 和 meta 文档,link 数组的结构与底层 unhead 引擎接受的格式一致,而后者也符合 WHATWG 的 rel="icon" 规范。

第二步:使用 useHead 按页面覆盖 favicon

有时你希望在特定路由上使用不同的图标。useHead 组合式函数允许你推送条目,仅覆盖当前页面的全局配置。

<script setup lang="ts">
useHead({
  link: [
    { rel: 'icon', type: 'image/svg+xml', href: '/icons/admin-favicon.svg' }
  ]
})
</script>

<template>
  <div>Admin Dashboard</div>
</template>

在 <script setup> 块顶部调用 useHead()。Nuxt 会处理 SSR 注入,因此覆盖会出现在初始 HTML 中——不会在 hydration 时闪现错误的图标,也无需客户端修补。

第三步:基于状态动态切换 favicon

希望 favicon 能响应通知数量或主题变化?将 useHead 与响应式 ref 或 computed 结合使用。

<script setup lang="ts">
const cartCount = useCartCount()

useHead({
  link: [
    {
      rel: 'icon',
      type: 'image/svg+xml',
      href: computed(() =>
        cartCount.value > 0
          ? `/icons/cart-${cartCount.value}.svg`
          : '/favicon.svg'
      )
    }
  ]
})
</script>

当 cartCount 变化时,计算属性 href 会更新。Nuxt 的 useHead 会跟踪响应性并就地重写 <link> 标签——无需整页刷新,也无需手动操作 DOM。如果你想进一步使用 canvas 生成徽章,底层模式在我们的 动态 favicon JavaScript 指南 中有所介绍。

第四步:支持暗黑模式 favicon

现代浏览器支持图标链接上的 media 属性。将其与 useHead 结合,无需任何 JavaScript 即可实现主题感知图标。

useHead({
  link: [
    { rel: 'icon', type: 'image/svg+xml', href: '/favicon-light.svg', media: '(prefers-color-scheme: light)' },
    { rel: 'icon', type: 'image/svg+xml', href: '/favicon-dark.svg', media: '(prefers-color-scheme: dark)' }
  ]
})

浏览器会根据用户的系统偏好选择正确的图标。这与我们的 favicon 暗黑模式指南 中描述的模式相同,但通过 Nuxt 的 head API 驱动,而非原始 HTML。

常见陷阱

总结

app.head 配置处理默认设置;useHead 处理所有动态需求。两者结合,覆盖了 Nuxt 应用通常需要的所有 favicon 场景——从单个静态图标到按页面切换和响应式徽章——无需借助第三方 head 插件或与 Nuxt 的默认设置对抗。

如果你还没有生成图标文件,Mzu favicondl 可以一键生成完整的多分辨率包(SVG、PNG、ICO、Apple Touch)。将文件放入 public/,在 app.head 中配置好,你的标签页很快就会看起来专业。