Image Optimization
Images are usually 40-60% of bandwidth. Here's how to fix that.
Key Insight
Images are typically the largest assets on a web page. Proper optimization can reduce page weight by 40-60% and significantly improve LCP. For cost analysis and CDN pricing, see the Cost Optimization Guide.
How Vercel Images Work
When you use next/image, Vercel:
- Transforms to requested size/format
- Caches at the edge
- Serves from cache on subsequent requests
You pay for:
- Transformations: Each unique width × height × quality combo
- Transfer: Optimized bytes sent to users
Using arbitrary widths like width={347} creates unique cached variants. 50 images with different widths = 50 transformations instead of 1.
The Standard Sizes Pattern
Define fixed sizes and stick to them:
export const IMAGE_SIZES = {
thumb: { width: 100, height: 100 },
card: { width: 320, height: 180 },
article: { width: 800, height: 450 },
hero: { width: 1280, height: 720 },
} as const;
export type ImageSize = keyof typeof IMAGE_SIZES;import Image from 'next/image';
import { IMAGE_SIZES, type ImageSize } from '@/lib/image-sizes';
export function OptimizedImage({ src, alt, size }: {
src: string;
alt: string;
size: ImageSize;
}) {
const { width, height } = IMAGE_SIZES[size];
return <Image src={src} alt={alt} width={width} height={height} quality={80} />;
}Now your app uses ~10 cached variants per image instead of dozens.
When to Use External CDN
Calculate break-even:
Monthly transformations × $0.05/1K = Vercel cost
Compare to: Cloudinary/Imgix planFor 50K+ transformations/month, external often wins:
export function cloudinaryLoader({ src, width, quality }: {
src: string;
width: number;
quality?: number;
}) {
const cloud = process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD;
const q = quality || 80;
return `https://res.cloudinary.com/${cloud}/image/fetch/w_${width},q_${q},f_auto/${encodeURIComponent(src)}`;
}<Image loader={cloudinaryLoader} src={url} width={800} height={600} alt="Photo" />Image Optimization Checklist
Use standard dimensions
Avoid arbitrary values like width={347}. Stick to predefined sizes to maximize cache hits.
Set quality to 80 The default 75 is often too aggressive. 80 provides better quality with minimal size increase.
Add priority to LCP images
Hero images and above-fold content should load immediately, not lazy load.
Evaluate external CDN for high volume At 50K+ transformations/month, Cloudinary or Imgix often beats Vercel's pricing.
Configure responsive sizes
Tell the browser what size image to fetch based on viewport width.
Use blur placeholders
Add placeholder="blur" with pre-generated blur data for better perceived performance.
Next: API Responses - the other big bandwidth opportunity.