Images are often the largest assets on modern websites, significantly impacting loading times and Core Web Vitals. In SvelteKit, you have two powerful approaches to image optimization: build-time processing with Vite plugins and runtime transformation through API routes. This guide shows you how to implement both strategies effectively, covering everything from format conversion to responsive image handling.
Build-Time Optimization with Vite Plugins
Build-time optimization processes your images during the Vite build process, creating optimized versions that are served as static assets. This approach is ideal for images that are part of your codebase and don't change frequently.
- 1Install vite-imagetoolsAdd the vite-imagetools plugin to your project: npm install -D vite-imagetools
- 2Configure ViteAdd the plugin to your vite.config.js file and configure default transformations
- 3Import and use optimized imagesImport images with query parameters for format, width, and quality options
- 4Generate responsive srcsetsUse the plugin's built-in functionality to generate multiple sizes for responsive images
// vite.config.js
import { defineConfig } from 'vite'
import { imagetools } from 'vite-imagetools'
export default defineConfig({
plugins: [
imagetools({
defaultDirectives: (url) => {
if (url.searchParams.has('webp')) {
return new URLSearchParams('format=webp&quality=80')
}
return new URLSearchParams('quality=80')
}
})
]
})// Component usage
import heroImage from './hero.jpg?w=1200;800;400&format=webp'
// The imported image is an object with src and srcset
const { src, srcset } = heroImageRuntime Optimization with API Routes
For dynamic images—such as user uploads, content from external APIs, or frequently changing assets—runtime optimization via SvelteKit API routes provides flexibility. This approach processes images on-demand while maintaining performance through caching.
- Dynamic content supportHandles user-generated and external images
- Flexible transformationsApply different optimizations based on request parameters
- No rebuild requiredImages can change without rebuilding the entire application
- Server processingRequires server resources for image processing
- Response timeFirst request may be slower while image is processed
- Caching complexityRequires careful caching strategy implementation
// src/routes/api/images/[transform]/[filename].js
import sharp from 'sharp'
export async function GET({ params }) {
const { transform, filename } = params
const [width, height, format] = transform.split('x')
// Fetch original image (from storage, database, or external source)
const imageBuffer = await fetchOriginalImage(filename)
// Process with sharp
const processedImage = await sharp(imageBuffer)
.resize(parseInt(width), height ? parseInt(height) : null)
.toFormat(format || 'webp')
.toBuffer()
return new Response(processedImage, {
headers: {
'Content-Type': `image/${format || 'webp'}`,
'Cache-Control': 'public, max-age=31536000, immutable'
}
})
}Implementing Responsive Images
Responsive images ensure users receive appropriately sized images for their viewport and device capabilities. Combine build-time optimization with responsive markup for the best results.
| Approach | Use Case | Implementation |
|---|---|---|
| Resolution switching | Different screen sizes | srcset with w descriptors |
| Art direction | Different crop ratios | picture element with media queries |
| Format switching | Browser capability support | picture element with type attributes |
<!-- Responsive image with format and resolution switching -->
<picture>
<source
type="image/avif"
srcset="/api/images/800x450/avif/photo.jpg 800w,
/api/images/1200x675/avif/photo.jpg 1200w"
sizes="(max-width: 800px) 100vw, 1200px">
<source
type="image/webp"
srcset="/api/images/800x450/webp/photo.jpg 800w,
/api/images/1200x675/webp/photo.jpg 1200w"
sizes="(max-width: 800px) 100vw, 1200px">
<img
src="/api/images/800x450/jpeg/photo.jpg"
srcset="/api/images/800x450/jpeg/photo.jpg 800w,
/api/images/1200x675/jpeg/photo.jpg 1200w"
sizes="(max-width: 800px) 100vw, 1200px"
alt="Responsive image example"
loading="lazy">
</picture>Caching Strategies for Optimized Images
Effective caching is crucial for performance. Build-time optimized images can use immutable caching, while runtime transformations benefit from content-based caching and CDN integration.
Choosing Between Build-Time and Runtime Optimization
The choice between build-time and runtime optimization depends on your specific use case. Here's when to use each approach:
Automate image optimization with Optimagio
Doing this by hand for every image does not scale. Optimagio optimizes and converts your images (WebP and AVIF) automatically across your API, web app, and CMS — so every page ships the smallest possible files without manual work. See plans and pricing →