Sveltekit loads images faster

Sveltekit image optimization

Speed Up SvelteKit by Importing Images from src/lib

image caching frontend dev tips sveltekit image guide svelte vite static files sveltekit best practices frontend optimization svelte image import sveltekit performance frontend caching sveltekit web performance svelte

When working on a SvelteKit project, it's common to drop images into the static/ directory and call it a day. It works, it’s simple, and it feels intuitive. But what if I told you that moving your images to src/lib/images could actually give you a noticeable performance boost?

Let’s explore why that’s the case — and why it might be time to rethink how your app handles images.


Why static/ Isn’t Always Ideal

The static/ folder is essentially a passthrough to the final build. Files here are served as-is and retain their original filenames. This is perfectly fine for assets that need fixed URLs, like robots.txt or favicons.

But here’s the catch: since these files don’t get any transformation during the build process, they also don’t get cache-busting hashes added to their filenames.

This leads to a problem: when a browser caches an image from static/, it has no way of knowing when the image changes unless it revalidates with the server. This means every time the browser loads your site, it has to send a request just to check if the image has changed. That might not sound like a big deal — but multiply that by 20 or 30 images on a page, and you’re suddenly looking at significant extra round-trips.


The src/lib/images Advantage

SvelteKit (via Vite) allows you to import images from anywhere inside the src/ directory. When you import an image from src/lib/images or similar, Vite processes it during the build:

  • A content-based hash is added to the filename. For example, hero.jpg might become hero.a8d3c1f1.jpg.
  • If the file changes, the hash changes — which automatically invalidates the browser cache.
  • If it doesn’t change, the browser can safely cache it forever.
  • This enables “immutable caching,” the gold standard for frontend performance.

This approach dramatically reduces unnecessary revalidation requests and improves loading speed, especially on mobile networks.


How to Use Images from src/lib

Here’s how you’d typically import and use an image:

<script>
  import hero from '$lib/images/hero.jpg';
</script>

<img src={hero} alt="Hero image" />

This guarantees the image is optimized, hashed, and cache-friendly out of the box.


Bonus Tip: Simplify Imports with svelte-preprocess-import-assets

Manually importing every image can get tedious. That’s where the svelte-preprocess-import-assets plugin comes in. It allows you to reference image paths as if they were in static/, while still benefiting from Vite’s asset handling.

Instead of:

<script>
  import logo from '$lib/images/logo.png';
</script>

<img src={logo} alt="Logo" />

You can write:

<img src="$lib/images/logo.png" alt="Logo" />

The plugin will handle the import behind the scenes during preprocessing. It’s a small quality-of-life improvement, but it adds up over time.


How to Configure svelte-preprocess-import-assets

  1. Install with your package manager:
npm install --save-dev svelte-preprocess-import-assets
  1. Include the preprocessor in your bundler’s Svelte plugin preprocess option:
import { importAssets } from 'svelte-preprocess-import-assets';

svelte({ preprocess: [importAssets()] });

// or in svelte.config.js
export default {
  preprocess: [importAssets()],
  // ... other Svelte options
};

When to Still Use static/

There are still valid use cases for the static/ directory:

  • Files that require fixed URLs (/robots.txt, /manifest.json, etc.)
  • Large files or user-uploaded content served from a CDN
  • Assets that don't need fingerprinting or hashing