We know Cloudflare is really good at optimizing images. It's flexible, fast and can really relieve next.js server from responsibility of optimizing images, especially if we have hundreds of them. I assume you already set up Cloudflare for your application and enabled image optimization feature. Let's do some coding now!
Create custom loader for Image component
Let's start with defining types of parameters our cloudflareLoader must accept. We're going to extend core Next.js types.
import NextImage, { ImageProps, ImageLoaderProps } from 'next/image';
type CloudflareImageLoaderProps = ImageLoaderProps & {
height?: number;
fit?: 'scale-down' | 'contain' | 'cover' | 'crop' | 'pad';
format?: 'jpeg' | 'webp' | 'avif';
};
Our custom loader will handle building an URL which points to cloudflare image optimization service. The service will optimize the image according to passed parameters, cache the image and serve it every time client makes a request.
const normalizeSrc = (src: string) => {
return src.startsWith('/') ? src.slice(1) : src;
};
export const cloudflareLoader = ({
src,
width,
height,
fit,
quality,
format = 'webp',
}: CloudflareImageLoaderProps) => {
const params = [`width=${width}`];
if (height) {
params.push(`height=${height}`);
}
if (fit) {
params.push(`fit=${fit}`);
}
if (quality) {
params.push(`quality=${quality}`);
}
if (format) {
params.push(`format=${format}`);
}
const paramsString = params.join(',');
return `https://my-nextjs-app.com/cdn-cgi/image/${paramsString}/${normalizeSrc(src)}`;
};
Use the loader in Image component
export const CloudflareImage = (props: ImageProps) => {
return <NextImage loader={cloudflareLoader} {...props} />;
};
It's ready to use! Make it handle all images which require optimization and work out the best quality settings which fit your project well!