Using Sirv CDN with Next.js Image
Next.js is a powerful "full-stack" React-based framework that powers lots of modern websites. It comes bundled with a powerful Image component that helps you generate image srcsets, resize local images and much more, but it can still benefit from Sirv's plethora of options and additional image optimization features.
In this article you'll learn how to integrate Sirv as a cusom loader for Next Image.
Live demo
Here's the demo repository with the code, a live demo and a CodeSandbox.
Getting started
- Create a Sirv account if you haven't already.
- Add a sirvLoader.js file to your project. In the code below, replace demo.sirv.com with your Sirv domain. You can get your Sirv domain URL from the Settings section of your account.
- Register the Sirv loader with Next Image in your next.config.js(or next.config.ts) file.
- Use Next Image like you're used to. Image props will be automatically identified and used to generate Sirv image URLs.
export default function SirvLoader({ src, width, quality}) { const url = new URL(`https://demo.sirv.com${src}`); // Don't forget to replace this with your Sirv URL. const params = url.searchParams; params.set('w', width.toString()); params.set('q', quality.toString()); return url.href; }
const nextConfig = { images: { loader: 'custom', loaderFile: './sirvLoader.js', // Change this to the correct path to your sirvLoader.js file }, }
<Image src="/yourImageUrl.jpg" alt="Image" width={500} height={300} quality={85} priority />
Advanced usage
Setting default values
If you want to use any of the Sirv transformation options that are outside of Next Image's scope, you can modify the sirvLoader.js to add additional default params.
For example, here's how you would set default values for format and profile options:
export default function SirvLoader({ src, width, quality }) { const url = new URL(`https://demo.sirv.com${src}`); const params = url.searchParams; //here we set the url params params.set('w', params.get('w') || width.toString()); params.set('q', (quality || 85).toString()); params.set('format', params.getAll('format').join(',') || 'optimal'); //here we set the default value for format to optimal if no other is specified. params.set('profile', params.get('profile') || "promo-text"); return url.href; }
This configuration will set the default format to 'optimal' and the default profile to 'promo-text'.
Dynamic values with a custom URL builder
Chances are, you'll need to update some particular Sirv URL params dynamically. Next Image doesn't allow you to do that out of the box, but this can be solved with a simple URL builder function.
For example, we need to dynamically update the image URL, 'profile', 'blur', and the 'profile' params. Let's add them to our app:
'use client'; import Image from 'next/image'; import { useState } from 'react'; export default function Home() { const [imgUrl, setImgUrl] = useState('/yourImageUrl.jpg'); const [sharpen, setSharpen] = useState(0); const [blur, setBlur] = useState(0); const [profile, setProfile] = useState('promo-text'); }
With that out of the way, we can move on to the URLbuilder function:
const buildImageSrc = () => { const params = new URLSearchParams(); // Only append profile, blur and sharpen if they have values if (profile) { params.append('profile', profile); } if (blur > 0) { params.append('blur', blur.toString()); } if (sharpen > 0) { params.append('sharpen', sharpen.toString()); } return `${imgUrl}?${params.toString()}`; };
Now onto the template. Let's use a form to modify the values:
<form> <label htmlFor="imgUrl"> Image Path </label> <select id="imgUrl" value={imgUrl} onChange={(e) => setImgUrl(e.target.value)}> <option value="/bag.jpg">/bag.jpg</option> <option value="/harris.jpg">/harris.jpg</option> </select> <label htmlFor="profile"> Profile </label> <select id="profile" value={profile} onChange={(e) => setProfile(e.target.value)}> <option value="OpenGraph">Sale</option> <option value="Vintage filter 2">Vintage Frame</option> </select> <label className="block text-white text-sm font-bold mb-2" htmlFor="blur"> Blur </label> <input id="blur" type="range" min="0" max="100" value={blur} onChange={(e) => setBlur(Number(e.target.value))} /> <label className="block text-white text-sm font-bold mb-2" htmlFor="sharpen"> Sharpen </label> <input id="sharpen" type="range" min="0" max="100" value={sharpen} onChange={(e) => setSharpen(Number(e.target.value))} /> </form>
And finally, here's how our Next Image component would look:
<Image src={buildImageSrc()} alt="Image" width={500} height={300} quality={85} profile={profile} blur={blur} sharpen={sharpen} priority />
As you can see, the Image Src is generated via our buildImageSrc function and the params we want to apply dynamically are being populated by our form values.
You might like to check out the source code of this Next Sirv demo, which also has a few extra options you'll see in the code. There's also a live demo for you to view.
Get expert help
If you would like any help configuring Sirv images in Next Image, please message the Sirv support team and we'll reply ASAP.