Using Sirv CDN with Next.js Image

On this page

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

  1. Create a Sirv account if you haven't already.
  2. 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.
  3. 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;
    }
    
  4. Register the Sirv loader with Next Image in your next.config.js(or next.config.ts) file.
  5. const nextConfig = {
      images: {
        loader: 'custom',
        loaderFile: './sirvLoader.js', // Change this to the correct path to your sirvLoader.js file
      },
    }
    
  6. Use Next Image like you're used to. Image props will be automatically identified and used to generate Sirv image URLs.
  7. <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.

Was this article helpful?

Get help from a Sirv expert

help ukraine help ukraine Powered by Ukrainian determination and British ingenuity

How can you support Ukraine