Image Optimisation with next/image
Image Optimisation with next/image
Status: Remediation tracked under PERF-02. No images are currently rendered via raw
<img>tags, but this guide establishes the standard for all future image work.
Background
The current application stores property photos as S3 keys and does not render them directly in the UI. However, as the product expands to include features like property photo galleries in check-in/check-out reports, using raw <img> tags would introduce measurable performance regressions.
Next.js ships a built-in <Image> component that provides:
| Feature | <img> | next/image |
|---|---|---|
| WebP / AVIF conversion | ✗ | ✓ (automatic) |
| Lazy loading | ✗ | ✓ (default) |
Responsive srcset | ✗ | ✓ (automatic) |
| Layout shift prevention (CLS) | ✗ | ✓ (reserved space) |
| Remote domain allowlisting | ✗ | ✓ (via remotePatterns) |
Configuration
Before serving images from the S3 bucket, add the domain to next.config.ts:
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: new URL(process.env.NEXT_PUBLIC_STORAGE_URL!).hostname,
},
],
},
};
export default nextConfig;
NEXT_PUBLIC_STORAGE_URLmust be set in your environment. See Environment Variables.
Usage Patterns
User Avatars (fixed dimensions)
For small, known-size images such as user avatars, always supply explicit width and height values:
import Image from 'next/image';
function Avatar({ url, name }: { url: string; name: string }) {
return (
<Image
src={url}
width={32}
height={32}
alt={`${name}'s avatar`}
className="rounded-full"
/>
);
}
Property Photos (fluid / responsive)
For images whose display size is determined by their container (e.g. a photo gallery), use the fill prop inside a relatively-positioned container:
import Image from 'next/image';
function PropertyPhoto({ s3Url, description }: { s3Url: string; description: string }) {
return (
<div className="relative w-full" style={{ aspectRatio: '16 / 9' }}>
<Image
src={s3Url}
fill
alt={description}
style={{ objectFit: 'cover' }}
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
);
}
The sizes prop tells the browser which image variant to download at each breakpoint, reducing unnecessary data transfer on mobile devices.
Checklist for New Image Work
- Import
Imagefromnext/image, not a raw<img>tag. - Add the remote hostname to
images.remotePatternsinnext.config.ts. - Provide
width+heightfor fixed-size images, orfill+ a positioned container for fluid images. - Supply a meaningful
altstring on every image. - Set the
sizesprop on fluid images to optimise bandwidth across breakpoints. - Test that the image domain resolves correctly in both development and production environments.
Related
- Next.js Image Optimisation docs
- PERF-02 audit (v0.1.152)