Vue Vite Favicon Public Folder: Step-by-Step Setup
You scaffold a fresh Vue 3 project with Vite, fire up the dev server, and check the browser tab. There's the default Vite logo sitting where your brand icon should be. The fix lives in your project's public/ folder, and wiring it correctly takes about three minutes once you know the Vite-specific gotchas.
New to favicons in Vite? Our Vite favicon guide covers the general setup; this page walks through the Vue project layout step by step.
Prerequisites
You'll need a Vue 3 project running on Vite, plus the favicon files you want to drop in. If you don't have them yet, generate a complete bundle (ICO, PNG, and SVG) using Mzu favicondl and download it ready to use. No webpack quirks, no copy-webpack-plugin rules — Vite handles the public folder as static assets, no configuration needed.
Step 1: Open the public/ Folder
Every Vue + Vite scaffold ships with a public/ directory at the project root. According to Vite's documentation on the public directory, anything you place here is copied to the build output unchanged and served at the root path.
That means public/favicon.ico is reachable as /favicon.ico, never /public/favicon.ico. Missing that distinction is the single most common reason Vue apps ship a broken tab icon to production.
Step 2: Drop In Your Favicon Files
Place your entire favicon package directly into public/:
Vite copies the whole folder to your dist/ output as-is — no imports, no transforms. Don't import these files from any Vue component; they're meant to stay outside the bundle. The complete breakdown of which sizes actually matter today lives in our Favicon Sizes Guide.
Step 3: Add link Tags to index.html
Open index.html at the project root — the same file where Vite mounts your Vue app. Add link rel="icon" declarations inside <head>:
Order matters here. Browsers pick the first rel="icon" entry they support, so place the SVG first for crisp scaling, PNG fallbacks next, and the legacy ICO last. All paths start with /, never /public/.
Step 4: Add Dark Mode SVG Support
If you want a dark mode swap, drop the media query inside the SVG itself rather than wiring up Vue reactivity for it:
Browsers swap the fill automatically — no watch() calls, no lifecycle hooks needed in the tab. For a deeper dive into the patterns, check our Favicon Dark Mode Guide.
Step 5: Verify in Dev and Production
Run npm run dev and confirm three things:
DevTools → Network → filter "favicon" shows every file returning 200 OK.
The browser tab shows your icon, not the default Vite mark.
curl http://localhost:5173/favicon.svg returns the SVG bytes.
Then run npm run build and inspect dist/. Every file from public/ should appear at the root of dist/, unchanged. If something is missing in production, your hosting's rewrite rules are likely stripping the path — check vercel.json or _redirects.
Common Pitfalls
Path typo: Writing /public/favicon.svg instead of /favicon.svg. Vite strips /public/ from the served URL — the file never resolves.
Wrong folder: Putting files in src/assets/ instead of public/. Bundled assets require an import statement and won't render at /favicon.svg.
Stale browser cache: Browsers cache the ICO aggressively. Hard-refresh with Cmd/Ctrl + Shift + R, or append ?v=2 to your icon URL.
Manifest mismatch: Your site.webmanifest references icon paths that don't match the actual filenames in public/. Both files need to agree line by line.
Wrapping Up
The Vue + Vite public folder workflow is one of the cleanest favicon setups in modern web dev. Drop your files, wire up the link tags in index.html, and Vite copies everything to dist/ exactly where you placed it. No plugin config, no head injection quirks, no Vue Router intercepting your requests — just static assets served from the root path.
Generate a complete favicon package with Mzu favicondl, paste the link tags into your index.html, and your Vue app will look polished in every browser tab.
用 Vite 初始化一个 Vue 3 项目,跑起 dev server 一看浏览器标签页——挂着的还是默认的 Vite logo。修起来其实就藏在项目的 public/ 目录里,只要摸清 Vite 那几个特有的坑,三分钟左右就能搞定。
环境准备
一个跑在 Vite 上的 Vue 3 项目,加上准备放进去的 favicon 文件。如果还没准备,可以用 Mzu favicondl 一键生成完整的 favicon 套件(ICO、PNG、SVG),下下来就能直接用。不用折腾 webpack,也不用配 copy-webpack-plugin——Vite 默认就把 public 目录当静态资源处理,零配置。
第一步:打开 public/ 目录
每个 Vue + Vite 脚手架项目根目录都自带一个 public/ 目录。Vite 关于 public 目录的文档 明确说过:放在这里的任何文件都会原样拷贝到构建产物里,并以根路径的形式对外提供。
Vue + Vite 的 public 目录流程,算是现代前端里最干净的 favicon 配置方式之一了。丢文件、在 index.html 里写好 link 标签,Vite 就把所有东西原封不动拷到 dist/。不用配插件,不用纠结 head 注入,Vue Router 也不会拦截你的请求——就是根路径下的静态资源。
Vue 3 のプロジェクトを Vite で新規作成して、開発 server を立ち上げ、ブラウザのタブを見てみます。ブランドアイコンを置くべき場所に、デフォルトの Vite ロゴが陣取っているはずです。修正はプロジェクトの public/ フォルダで行います。Vite 特有の落とし穴さえ押さえれば、設定は 3 分程度で完了します。
Vue + Vite の public フォルダを使ったワークフローは、モダンな Web 開発の中でも特にクリーンな favicon 設定の一つです。ファイルを配置し、index.html に link タグを記述すれば、Vite がすべてをそのまま dist/ にコピーします。プラグインの設定も、head への注入の挙動も、Vue Router によるリクエストの割り込みも一切なく、ルートパスから配信される static な asset として扱われます。
Mzu favicondl で favicon パッケージを生成し、index.html に link タグを貼り付ければ、あらゆるブラウザタブで Vue アプリがきちんと見えるようになります。
Vite로 새 Vue 3 프로젝트를 생성하고 개발 서버를 띄운 뒤 브라우저 탭을 살펴보면, 브랜드 아이콘이 있어야 할 자리에 기본 Vite 로고가 자리 잡고 있습니다. 해결책은 프로젝트의 public/ 폴더에 있으며, Vite 관련 함정만 알고 나면 올바르게 연결하는 데 약 3분 정도면 충분합니다.
사전 요구 사항
Vite 기반의 Vue 3 프로젝트와 함께, 적용하려는 favicon 파일이 필요합니다. 아직 준비하지 않았다면 Mzu favicondl을 사용해 ICO, PNG, SVG로 구성된 전체 번들을 생성해 즉시 사용할 수 있도록 다운로드하시기 바랍니다. webpack 관련 특이 사항이나 copy-webpack-plugin 규칙은 필요 없습니다. Vite는 별도의 설정 없이 public 폴더를 정적 자산으로 처리합니다.
1단계: public/ 폴더 열기
모든 Vue + Vite 스캐폴드에는 프로젝트 루트에 public/ 디렉터리가 포함되어 있습니다. Vite의 public 디렉터리 문서에 따르면, 여기에 배치한 파일은 변환 없이 빌드 출력으로 복사되어 루트 경로에서 제공됩니다.
즉, public/favicon.ico는 /favicon.ico로 접근할 수 있으며, /public/favicon.ico로는 접근할 수 없습니다. 이 차이를 놓치는 것이 Vue 애플리케이션이 프로덕션 환경에서 깨진 탭 아이콘을 그대로 노출하는 가장 흔한 원인입니다.
Vite는 폴더 전체를 그대로 dist/ 출력으로 복사합니다. import나 변환 과정이 발생하지 않습니다. Vue 컴포넌트에서 이 파일들을 import하지 마시기 바랍니다. 번들 외부에 두는 것이 올바른 방식입니다. 오늘날 실제로 의미 있는 사이즈에 대한 자세한 분석은 Favicon Sizes Guide에서 확인하실 수 있습니다.
3단계: index.html에 link 태그 추가하기
프로젝트 루트의 index.html 파일을 엽니다. Vite가 Vue 앱을 마운트하는 바로 그 파일입니다. <head> 안에 link rel="icon" 선언을 추가합니다.
여기서 순서가 중요합니다. 브라우저는 지원 가능한 첫 번째 rel="icon" 항목을 선택하기 때문에 SVG를 가장 앞에 두고 선명한 스케일링을 확보한 다음 PNG 폴백을 이어서 배치하고, 레거시 ICO는 마지막에 둡니다. 모든 경로는 /로 시작해야 하며 /public/로 시작해서는 안 됩니다.
4단계: 다크 모드 SVG 지원 추가하기
다크 모드 전환을 적용하고 싶다면 Vue의 reactivity를 연결하기보다 SVG 내부에 media query를 직접 삽입하는 방식을 권장합니다.
curl http://localhost:5173/favicon.svg 명령이 SVG 바이트를 반환하는지 확인합니다.
이어서 npm run build를 실행하고 dist/를 검사합니다. public/의 모든 파일이 변경 없이 dist/ 루트에 나타나야 합니다. 프로덕션 환경에서 누락된 파일이 있다면 호스팅의 rewrite 규칙이 경로를 제거하고 있을 가능성이 높으므로 vercel.json 또는 _redirects를 확인하시기 바랍니다.
자주 발생하는 문제
경로 오타:/favicon.svg 대신 /public/favicon.svg로 작성하는 경우입니다. Vite는 제공되는 URL에서 /public/을 제거하기 때문에 파일이 절대 해석되지 않습니다.
잘못된 폴더 사용:public/ 대신 src/assets/에 파일을 배치하는 경우입니다. 번들된 자산은 import 문이 필요하며 /favicon.svg 경로로 렌더링되지 않습니다.
브라우저 캐시 문제: 브라우저는 ICO를 적극적으로 캐싱합니다. Cmd/Ctrl + Shift + R로 강력 새로 고침을 하거나 아이콘 URL에 ?v=2를 추가하시기 바랍니다.
Manifest 불일치:site.webmanifest가 public/의 실제 파일명과 일치하지 않는 아이콘 경로를 참조하는 경우입니다. 두 파일이 줄 단위로 일치해야 합니다.
마무리
Vue + Vite의 public 폴더 워크플로우는 현대 웹 개발에서 가장 깔끔한 favicon 설정 방식 중 하나입니다. 파일을 배치하고 index.html에 link 태그를 연결하기만 하면 Vite가 모든 것을 배치한 위치 그대로 dist/로 복사합니다. 플러그인 설정, head 주입 관련 특이 사항, Vue Router의 요청 가로채기 없이 오직 루트 경로에서 제공되는 정적 자산만으로 구성됩니다.
Mzu favicondl로 완전한 favicon 패키지를 생성하고 link 태그를 index.html에 붙여 넣으면 Vue 앱이 모든 브라우저 탭에서 완성도 있게 보이게 됩니다.
Creas un proyecto Vue 3 con Vite, arrancas el servidor de desarrollo y miras la pestaña del navegador. Ahí está el logo de Vite por defecto donde debería estar el icono de tu marca. La solución está en la carpeta public/ de tu proyecto, y configurarlo correctamente lleva unos tres minutos una vez que conoces los detalles específicos de Vite.
Requisitos previos
Necesitas un proyecto Vue 3 ejecutándose con Vite, además de los archivos de favicon que quieras usar. Si aún no los tienes, genera un paquete completo (ICO, PNG y SVG) con Mzu favicondl y descárgalo listo para usar. Sin rarezas de webpack, sin reglas de copy-webpack-plugin — Vite trata la carpeta public como activos estáticos, sin configuración adicional.
Paso 1: Abre la carpeta public/
Todo proyecto Vue + Vite incluye un directorio public/ en la raíz del proyecto. Según la documentación de Vite sobre el directorio public, cualquier cosa que coloques aquí se copia sin cambios a la salida de compilación y se sirve en la ruta raíz.
Eso significa que public/favicon.ico es accesible como /favicon.ico, nunca como /public/favicon.ico. No entender esta distinción es la causa más común de que las aplicaciones Vue lleguen a producción con un icono de pestaña roto.
Paso 2: Coloca tus archivos de favicon
Coloca todo tu paquete de favicon directamente en public/:
Vite copia toda la carpeta a tu salida dist/ tal cual — sin imports, sin transformaciones. No hagas import de estos archivos desde ningún componente Vue; están destinados a permanecer fuera del bundle. El desglose completo de qué tamaños importan realmente hoy está en nuestra Guía de Tamaños de Favicon.
Paso 3: Añade etiquetas link en index.html
Abre index.html en la raíz del proyecto — el mismo archivo donde Vite monta tu aplicación Vue. Añade las declaraciones link rel="icon" dentro de <head>:
El orden importa aquí. Los navegadores eligen la primera entrada rel="icon" que soporten, así que coloca el SVG primero para una escala nítida, los PNG como respaldo a continuación, y el ICO heredado al final. Todas las rutas comienzan con /, nunca con /public/.
Paso 4: Añade soporte para modo oscuro en SVG
Si quieres un cambio para modo oscuro, coloca la media query dentro del propio SVG en lugar de configurar la reactividad de Vue para ello:
Los navegadores cambian el relleno automáticamente — sin llamadas a watch(), sin hooks de ciclo de vida necesarios en la pestaña. Para un análisis más profundo de los patrones, consulta nuestra Guía de Modo Oscuro para Favicon.
Paso 5: Verifica en desarrollo y producción
Ejecuta npm run dev y confirma tres cosas:
DevTools → Red → filtrar "favicon" muestra que cada archivo devuelve 200 OK.
La pestaña del navegador muestra tu icono, no la marca de Vite por defecto.
curl http://localhost:5173/favicon.svg devuelve los bytes del SVG.
Luego ejecuta npm run build e inspecciona dist/. Cada archivo de public/ debería aparecer en la raíz de dist/, sin cambios. Si falta algo en producción, es probable que las reglas de reescritura de tu hosting estén eliminando la ruta — revisa vercel.json o _redirects.
Errores comunes
Error de ruta: Escribir /public/favicon.svg en lugar de /favicon.svg. Vite elimina /public/ de la URL servida — el archivo nunca se resuelve.
Carpeta incorrecta: Colocar archivos en src/assets/ en lugar de public/. Los activos empaquetados requieren una declaración import y no se mostrarán en /favicon.svg.
Caché del navegador obsoleta: Los navegadores cachean el ICO de forma agresiva. Haz una recarga forzada con Cmd/Ctrl + Shift + R, o añade ?v=2 a la URL de tu icono.
Manifest desajustado: Tu site.webmanifest referencia rutas de iconos que no coinciden con los nombres de archivo reales en public/. Ambos archivos deben coincidir línea por línea.
Conclusión
El flujo de trabajo de la carpeta public en Vue + Vite es uno de los sistemas de favicon más limpios en el desarrollo web moderno. Coloca tus archivos, configura las etiquetas link en index.html, y Vite copia todo a dist/ exactamente donde lo pusiste. Sin configuración de plugins, sin rarezas de inyección en el head, sin Vue Router interceptando tus solicitudes — solo activos estáticos servidos desde la ruta raíz.
Genera un paquete completo de favicon con Mzu favicondl, pega las etiquetas link en tu index.html, y tu aplicación Vue se verá pulida en cada pestaña del navegador.
Generate Your Vue Favicon Package in Seconds
Drop a complete ICO, PNG, and SVG bundle into your Vue + Vite project's public folder. No sizing math, no manual exports.