你把 favicon.svg 放进了 Vite 的 public 文件夹,保存后,浏览器标签页仍然显示一个空白方块。构建正常,文件就在那里,但浏览器就是找不到它。这种情况发生在开发者把 Vite 的 public 目录当作普通静态文件夹处理时——却忽略了 Vite 提供这些文件的一个关键规则。

public 文件夹是 Vite 为需要稳定、无哈希 URL 的资源准备的逃生舱。Favicon 是教科书式的用例——也是 Vite 初学者最常见的困惑来源。

为什么 Favicon 应该放在 Vite 的 public 文件夹

Vite 会对 src/ 中导入的资源进行哈希处理,以便缓存破坏(比如 assets/logo-a3f9c2.svg)。这对 JS 和 CSS 很好,但对 favicon 来说很糟糕。浏览器会积极缓存 favicon,搜索引擎也需要一个可预测的 URL 来在结果中显示你的图标。

public/ 中的文件完全绕过打包器。根据 Vite 官方文档,此目录中的任何内容都会被复制到构建输出的根目录,并在根路径下提供。所以 public/favicon.svg 变成 /favicon.svg——而不是 /public/favicon.svg。只是文件名,前面加一个斜杠。

前提条件

步骤 1:将 Favicon 文件放入 public/

将你的图标文件直接放在项目根目录的 public/ 目录中。大多数 Vite 脚手架会自动创建这个文件夹。

my-vite-app/
├── public/
│   ├── favicon.svg
│   ├── favicon.ico
│   └── apple-touch-icon.png
├── src/
├── index.html
└── package.json

使用简单、常规的文件名。浏览器无需额外配置就能在根目录找到 favicon.svg、favicon.ico 和 apple-touch-icon.png。

步骤 2:使用根相对路径引用文件

打开项目根目录下的 index.html(不是 public/index.html——那个文件在 Vite 中不存在)。在 <head> 中添加 link 标签,使用以 / 开头的绝对路径。这是 Vite 项目中唯一需要硬编码资源路径的地方,因为 public 文件夹有意跳过导入解析器。

<head>
  <link rel='icon' type='image/svg+xml' href='/favicon.svg'>
  <link rel='icon' type='image/x-icon' href='/favicon.ico'>
  <link rel='apple-touch-icon' href='/apple-touch-icon.png'>
</head>

HTML 规范将 rel='icon' 定义为声明 favicon 的标准方式(WHATWG HTML Living Standard)。浏览器会根据 type 和 sizes 属性选择最佳匹配。

步骤 3:添加深色模式变体

现代浏览器支持第二个 SVG,在深色主题下自动激活。添加另一个带有媒体查询的 link 标签,这样当用户的系统切换到深色模式时,他们能看到正确的图标。

<link rel='icon' type='image/svg+xml' href='/favicon.svg' media='(prefers-color-scheme: light)'>
<link rel='icon' type='image/svg+xml' href='/favicon-dark.svg' media='(prefers-color-scheme: dark)'>

关于深色模式 SVG favicon 的更深入覆盖,请参阅我们的 favicon 深色模式指南。

步骤 4:验证构建输出

运行 npm run build 并检查 dist/。你的 favicon 文件应该出现在根目录,未被任何打包器处理。

dist/
├── assets/
├── favicon.svg
├── favicon.ico
└── index.html

你也可以启动 npm run preview,然后在 DevTools 中打开 Network 标签。你应该看到对 favicon.svg、favicon.ico 和 apple-touch-icon.png 的请求返回 200,而不是 404。

常见陷阱

大多数 Vite favicon 问题都源于以下错误之一。如果你的标签页是空白或显示通用图标,请先检查这个列表。

当 public 文件夹不够用时

public 文件夹是静态、不变的 favicon 的正确归属。它为你提供稳定的 URL,浏览器可以可靠地缓存,搜索引擎也可以索引。如果你以后需要动态 favicon——通知徽章、用户头像、实时状态指示器——你需要 JavaScript 在运行时交换 href 属性。我们的 动态 favicon JavaScript 指南详细介绍了这种模式。

需要帮助先生成正确的图标文件吗?Mzu favicondl 可以从单个源图像生成 SVG、PNG、ICO 和 Apple Touch 变体。将它们放入 public/,添加 link 标签,你的 Vite 应用就能在几分钟内拥有专业的标签页外观。