If you've been working with Vite for a while, you've probably noticed there are two main places to put your assets: the public
folder and the src
folder. And if you're like most developers, you've probably wondered when to use which one.
The good news? Once you understand the difference, it's actually pretty straightforward. Let me break it down for you.
What's the Deal with These Two Folders?
In any Vite project, you'll see these two folders right off the bat. They both handle assets, but they work in completely different ways.
The public
folder is like your website's front door. Anything you put in here gets served directly to browsers without any processing. No bundling, no optimization, no fancy transformations. It's just there, as-is.
The src
folder (and specifically src/assets/
) is where Vite gets to work its magic. Assets here go through the build process, get optimized, and can be imported into your components.
When to Use the Public Folder
The public folder is perfect for static assets that need to be accessible via direct URLs. Here's when you should reach for it:
Your favicon, apple-touch-icon, and other meta images should live in public
. These need to be referenced by absolute paths in your HTML, and browsers expect them at specific locations.
<!-- In your index.html -->
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
SEO and Bot Files
Files like robots.txt
, sitemap.xml
, and manifest.json
belong in public. Search engines and bots look for these at root-level paths by default typically.
Got a big video file or high-resolution images that don't need processing? Public folder is your friend. Since these bypass the build process, they won't slow down your development or production builds.
Dynamic Asset References
If you're generating image URLs dynamically or referencing assets in ways that can't be statically analyzed, public is the way to go.
// This works with public folder assets
const imageUrl = `/images/user-${userId}.jpg`;
External Library Assets
Some third-party libraries expect assets at specific public paths. Rather than fighting with import statements, just drop them in public.
When to Use Src Assets
The src folder is where you want most of your assets to live, especially if you're building a modern, optimized application. Here's when src assets shine:
Component-Specific Images
Images that are tied to specific components should be in src. This keeps everything organized and makes it easy to see what assets are actually being used.
import heroImage from '../assets/hero-background.jpg';
function Hero() {
return <img src={heroImage} alt="Hero" />;
}
Icons and SVGs
Small icons and SVGs are perfect for src assets. They can be optimized, tree-shaken, and even imported as React components in some setups.
CSS Background Images
When you're using images in CSS files, src assets work great because the build process can optimize and fingerprint them.
.hero {
background-image: url('./assets/hero-bg.jpg');
}
Assets That Need Processing
If you want Vite to optimize, compress, or transform your assets, they need to be in src. This includes automatic image optimization and format conversion.
The Technical Differences
Understanding what happens under the hood helps you make better decisions:
Public Assets
- Served directly by the dev server
- No processing or optimization
- Always available at
/filename.ext
- Not included in bundle analysis
- Perfect for files that need predictable URLs
Src Assets
- Processed through Vite's build pipeline
- Get content-based hashes for cache busting
- Can be imported and used in JavaScript
- Undergo optimization and compression
- Only included in final bundle if imported
Best Practices I've Learned
After working with both approaches, here are some patterns that work well:
Use Src by Default
Start with src assets for most things. It's the more "modern" approach and gives you better optimization and development experience.
Keep Public Minimal
Only use public for assets that absolutely need to be there. The more you put in src, the better your build tooling can help you.
Organize by Purpose
I like to structure my src assets by feature or component, while keeping public assets flat and focused on essential static files.
src/
assets/
components/
hero/
background.jpg
overlay.png
icons/
arrow.svg
user.svg
public/
favicon.ico
robots.txt
og-image.jpg
Large files that don't change often can go in public to avoid rebuild times. Small, frequently changing assets benefit from src's processing.
Common Mistakes to Avoid
Don't put everything in public
just because it's easier. You'll miss out on optimizations and make your app slower.
Don't try to import public assets. They're not part of the module system, so imports won't work.
Don't put frequently changing assets in public
if you want cache busting. Src assets get automatic hashes for better caching.
The Bottom Line
The choice between public and src assets really comes down to this: Do you need the asset to be processed and optimized by your build tools? If yes, use src. If you need it to be available at a predictable URL without processing, use public.
Most of the time, you'll want src assets for a better developer experience and optimized production builds. But don't be afraid to use public when it makes sense - that's what it's there for.
Remember, these aren't hard rules. Every project is different, and you might find patterns that work better for your specific use case. The key is understanding what each folder does so you can make informed decisions.
Happy coding!