Custom Next.js image loader problem with Prismic image optimization for SVG

Hi! Currently, I'm working on implementing Imgix img optimization that will work in tandem with Next.js.

Based on the Next.js docs for custom image loaders I created a loader, that passes parameters understandable for the Imgix platform.

export const imageLoader = ({ src, width, quality }) => {
    return `${src}&w=${width}&q=${quality || 75}`;
};

It works very well for all images, except for SVG. I found this Prismic blog post Changes to how we handle SVG's, which points out, that SVGs should not have the additional parameters added to them, because they are served without the help of the Imgix platform - fair enough. It also shows how to differentiate between SVGs and other img types. So I changed the code accordingly:

export const imageLoader = ({ src, width, quality }) => {
  if (src.includes("images.prismic")) {
    return `${src}&w=${width}&q=${quality || 75}`;
  }
  return src;
};

But because of the lack of those optimization parameters that Next.js expects, I get this warning in the console:

Image with src "https://my-website.cdn.prismic.io/my-website/some_vector_iamge.svg" has a "loader" property that does not implement width. Please implement it or use the "unoptimized" property instead.
Read more: https://nextjs.org/docs/messages/next-image-missing-loader-width

I could add the "unoptimized" property to my Image components, where I use the SVG and it will work. But the thing is, a user in the future could change any image in the Prismic dashboard to the SVG, and it would break in other places.

Do you have an idea how to tackle this problem? I imagine the img service should accept all of those parameters even for SVG and always serve the basic SVG just skipping all params. I think it would be great to check how it's handled by other next.js built-in image loaders.

And if there is no good solution for now, I can create a wrapper component for the Next.js <Image />, that will check the src prop and dynamically add the "unoptimized" property based on the domain. That's not ideal since I will duplicate the logic in 2 places, but that's at least some way forward.

I'd love to hear from you, what do you think, and if you already track this issue. Thanks!

Hello @konrad.nojman

Thanks for reaching out to us.

SVGs don’t come through imgix, and your loader doesn’t have an amazon s3 bucket. You have if loop here to deal with imgix images. SVGs come directly from Amazon S3, so you need to set up an if case for Amazon S3.

Thanks,
Priyanka

Thanks @Priyanka for the response!

I think SVGs are not linked directly from Amazon S3 buckets. Looks like you use the CDN to host them - in my case they came from the domain https://{my-website}.cdn.prismic.io.

Since I understand the SVGs are not going through the imgix service, I can't add any additional parameters to the URL (and that's fine).
I guess for now to handle the Next.js warning with the loader I will add the wrapper component that depending on the URL adds an "unoptimized" prop to the image if the image is an SVG and doesn't go through imgix.
So for clarity, the idea will be (but this URL logic will probably live somewhere else):

import Image from "next/image";
// ...
<Image
  src={slice.primary.image.url}
  alt={slice.primary.image.alt}
  width={slice.primary.image.dimensions.width}
  height={slice.primary.image.dimensions.height}
  loader={imageLoader}
  // If the image from "images.prismic" domain, it went through imgix and can be optimized.
  unoptimized={slice.primary.image.url.includes("images.prismic") ? false : true}
/>

Hi @konrad.nojman Just FYI, this is the code I use for Prismic Templates and it's been working quite well. I don't have to think about loaders and SVGs at all. In my next.config.js, I add the following options

    images: {
      loader: "imgix",
      path: "",
      deviceSizes: [82, 110, 140, 640, 750, 828, 1080, 1200, 1920, 2048, 3840],
      domains: [
        `prismic-templates-website.cdn.prismic.io`,
        "images.prismic.io",
        "prismic-io.s3.amazonaws.com",
      ],
    },

Obviously replace the first domain with your own repo.

Hope this helps!

2 Likes

Oh! You are right! I don't know how I didn't catch, that imgix is on the list of built-in next.js loaders.
Maybe I thought, that since SVGs are coming from a different source, I need a custom loader :thinking:

Anyways, let me check your suggestion, and hopefully, it works out of the box :raised_hands:
Since you already said you don't have any problems with images, I'm tagging your response as a solution :slight_smile: Thanks again @kris!