Next.js Favicon:现代 App Router 指南
你刚启动了一个全新的 Next.js 项目,把一个 favicon.ico 文件扔进了 public 文件夹,然后……什么也没发生。或者更糟,它在本地能用,但在生产环境就坏了。这是怎么回事?
如果这听起来很耳熟,你可能正巧碰上了旧的 pages router 和现代 App Router 之间的差异。好消息是,一旦你了解了它的约定,新的方式其实更简单、更强大。
官方方式:基于文件的元数据
忘了手动在你的 layout.tsx 文件里添加 <link> 标签吧。Next.js App Router 使用一种特殊的基于文件的系统。你只需将特定命名的图标文件放在你的 app 目录下,Next.js 就会自动为你生成必要的 HTML head 标签。
这是我推荐的方法。它更整洁,不易出错,并且利用了框架的内置优化。
分步指南:添加你的 Favicon
我们用不到五分钟的时间搞定它。除了一个正在运行 App Router 的 Next.js 项目外,不需要任何先决条件。
第一步:准备你的图标文件
为了实现广泛的兼容性,你需要几个关键文件。虽然你可以自己创建这些文件,但使用生成器能确保它们的尺寸和格式都正确无误。(不害臊地插播一句:我们的免费 favicon 生成器能完美处理这一切)。
favicon.ico:经典格式。旧版浏览器需要它。icon.png或icon.svg:现代高分辨率图标。我强烈推荐使用 SVG。我们有一整篇关于 SVG favicon 优势的指南。apple-icon.png:当用户将你的网站添加到他们的 iOS 主屏幕时使用。可以查看我们的 Apple Touch Icon 指南了解具体细节。
第二步:将图标放在 `app` 目录的根路径下
这是最重要的一步。将你生成的图标直接移动到 /app 文件夹中。不要把它们放在 /public 文件夹里。
你的项目结构应该看起来像这样:
app/
├── layout.tsx
├── page.tsx
├── favicon.ico <-- 用于旧版浏览器
├── icon.svg <-- 用于现代浏览器 (推荐)
└── apple-icon.png <-- 用于 iOS 主屏幕
public/
└── ... (你的其他静态资源)
Next.js 会自动检测这些文件,并在你网站的 <head> 中生成相应的 <link> 标签。
第三步:移除任何旧的或手动的声明
如果你的 public 文件夹里有一个旧的 favicon.ico,请删除它。虽然 /app 目录下的文件会优先使用,但最好还是避免混淆。
另外,检查你的根 layout.tsx 文件,移除任何手动添加的 <link rel="icon" ...> 标签。基于文件的方法使它们变得多余。
第四步:验证结果
运行你的开发服务器 (npm run dev),并检查页面的源代码。你应该能看到 Next.js 已经为你生成了这些标签,大概是这样:
<head>
...
<link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="any">
<link rel="icon" href="/icon.svg" type="image/svg+xml" sizes="any">
<link rel="apple-touch-icon" href="/apple-icon.png" type="image/png" sizes="any">
...
</head>
看到这些标签就意味着它成功了。框架已经处理好了一切。
真实案例:GitHub 是怎么做的
好奇大公司是怎么处理这个问题的吗?看看 GitHub。他们提供了一个 favicon.ico,为不同设备提供了多种尺寸的 PNG,还有一个用于 Safari 固定标签页的特殊单色 SVG。Next.js 基于文件的方法就是为了能自动构建这种强大的、支持多设备的方案,让你不必手动编写所有这些 <link> 标签。
需要避免的常见陷阱
如果你的图标没有显示出来,通常是以下三个原因之一。
1. `public` 文件夹的陷阱
再次强调,对于像 favicon 这样的元数据文件,在现代 Next.js 中,app 目录才是正确的位置。虽然 public 文件夹仍然可以用于存放通用静态资源,但放在 /app 目录下的图标有特殊含义并拥有更高优先级。
2. 顽固的浏览器缓存
你的代码完美无缺,但你看到的仍然是旧图标(或者没有图标)。这几乎总是浏览器的锅。浏览器会非常积极地缓存 favicon。
简单的页面刷新通常是不够的。你需要进行硬刷新或清除浏览器缓存。如果你卡住了,我们写了一篇关于如何强制清除 favicon 缓存的详细指南。
3. 不正确的文件名
favicon.ico、icon.png、icon.svg 和 apple-icon.png 这些名字不是随便起的。它们是 Next.js 特意寻找的约定。像 my-icon.svg 这样的拼写错误是不会被自动识别的。
就是这样。通过遵循基于文件的约定,你是顺应框架而行,而不是与之对抗。你可以免费获得优化且正确的 HTML,并且你的项目能保持整洁。再也不用为了在浏览器标签页上显示一个小小的品牌标志而和 <head> 标签搏斗了。