next.js icon indicating copy to clipboard operation
next.js copied to clipboard

next/image does not work with CDN

Open gabor-at-reed opened this issue 3 years ago • 11 comments

Run next info (available from version 12.0.8 and up)

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Pro
Binaries:
  Node: 16.13.0
  npm: 8.1.0
  Yarn: N/A
  pnpm: N/A
Relevant packages:
  next: 12.0.8
  react: 17.0.2
  react-dom: 17.0.2

What version of Next.js are you using?

12.0.8

What version of Node.js are you using?

16.3.0

What browser are you using?

Chrome

What operating system are you using?

Windows, Linux

How are you deploying your application?

Other platform

Describe the Bug

The issue relates to a previous bug, but that case was closed. However, I believe the issue still persists.

We have the CDN URL specified in the assetPrefix:

// next.config.js
module.exports = {
    assetPrefix: 'https://cdn.example.com'
}

Following the guide from the docs:

Files in the public folder; if you want to serve those assets over a CDN, you'll have to introduce the prefix yourself

In the code we have the following Image tag:

<Image
    src={`${assetPrefix}/images/cat.jpg`}
    alt="Cat"
    width={30}
    height={30}
/>

But the result in the markup is like this:

<img alt="Cat" src="/_next/image?url=https%3A%2F%2Fcdn.example.com%2Fimages%2Fcat.jpg&amp;w=64&amp;q=75" decoding="async" data-nimg="intrinsic" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" srcset="/_next/image?url=https%3A%2F%2Fcdn.example.com%2Fimages%2Fcat.jpg&amp;w=32&amp;q=75 1x, /_next/image?url=https%3A%2F%2Fcdn.example.com%2Fimages%2Fcat.jpg&amp;w=64&amp;q=75 2x">

Expected Behavior

The expected behaviour should be that the initiator URL (src="/_next/image?url...) should also have the CDN prefix, like src="https://cdn.example.com/_next/image?url....

All compiled assets are loaded fine from the CDN by the way... so the _next folder is served from the CDN. That proves the assetPrefix setting is working properly, only the Image is failing.

To Reproduce

Use both <Image> and assetPrefix. Load image from the public folder.

gabor-at-reed avatar Jan 20 '22 09:01 gabor-at-reed

Any updates from Vercel's side on this?

gabor-at-reed avatar Feb 17 '22 12:02 gabor-at-reed

Running into the same issue. This was reported here as well https://github.com/vercel/next.js/issues/20968 and it was never fixed. cc @ijjk since you were part of that conversation.

andreisoare avatar Feb 24 '22 23:02 andreisoare

Looking at the Image component code it seems the default image loader uses the path property in next.config.js -> images. I was able to solve the author's issue with the following config:

images: {
  domains: [
    ...
  ],
  path: 'https://cdn.com/_next/image',
},

(fwiw I'm using Cloudflare CDN, but that shouldn't matter)

andreisoare avatar Feb 24 '22 23:02 andreisoare

@andreisoare, I'll try your suggested hack, but I don't think that should be the solution. Also, I have a strong feeling that we won't be able to use this path hack (even if it's working) for other reasons. I'll let you know next week how it goes. But as I said, the ultimate goal here is the assetPrefix should be fixed.

gabor-at-reed avatar Mar 08 '22 15:03 gabor-at-reed

Hi I'm running into the same issue. @andreisoare I tried your hack. This is my next.config.js

module.exports = {
  assetPrefix: process.env.VERCEL_URL,
  images: {
    domains: [process.env.VERCEL_URL],
    path: `${process.env.VERCEL_URL}/_next/image`,
  },
};

FWIW the reason I'm using VERCEL_URL as the asset prefix is that my production site is living on a subdomain of another site. The site the client sees is isha.sadhguru.org. Then we setup a reverse proxy from isha.sadhguru.org/isha-yoga-center-california to the url of a Vercel website.

To get assets to load properly on the isha.sadhguru.org website, I need the URLs to be absolute paths to the underlying vercel URL, as relative paths would not get properly reverse-proxied back to the vercel URL.

Regardless, as far as the overall issue is concerned, I'm facing the same basic problem: NextJS Image does not work once I put an assetPrefix. And the path hack didn't seem to fix it.

Are there any other suggested hacks we can use while we wait for the vercel team to fix the underlying issue?

frahman5 avatar Mar 10 '22 05:03 frahman5

Creating a custom loader might help: https://nextjs.org/docs/api-reference/next/image#loader

neeraj3029 avatar Mar 12 '22 06:03 neeraj3029

Is it fixed?

yf-hk avatar Jun 17 '22 00:06 yf-hk

Is it fixed?

ebameng avatar Jul 01 '22 07:07 ebameng

same problem

fabriciosautner avatar Aug 22 '22 21:08 fabriciosautner

The same. I'm wondering about the modern JS ecosystem. Even the simple CDN image rendering might be an issue. So disappointing. P.S. The problem could be in the loader, I guess, because I played with the different loaders and in my case, the akamai was the problem somehow. I changed it to the default one and the images started to loading via the correct URL. Don't have any idea why. Here is my config:

  images: {
      domains: ['imagedelivery.net'],
    // loader: 'akamai',
    // assetPrefix: 'https://imagedelivery.net/'
  },

The problem in this solution that when I try to compile Next.js as the production static files, the default loader throws an error but Akamai does not. Weird. So need to play with it a bit more

velidan avatar Sep 01 '22 08:09 velidan

We have a use case of more complex proxying where the initial page request is proxied to the next.js page running on a different domain. Fetching static assets with an assetPrefix afterwards is fine apart from optimised images. What @frahman5 and some of the others proposed with the "path" config entry solved our issue and the need for assetPrefix to apply to images. I am not sure if this was the intended use for the config entry though.

ivstiv avatar Oct 26 '22 15:10 ivstiv

any update on this one?

rzubrycki avatar Jul 17 '23 08:07 rzubrycki

Any update here?

stefann01 avatar Sep 15 '23 22:09 stefann01

Any updates on the CDN issue?

BohdanCredible avatar Nov 28 '23 14:11 BohdanCredible

Just override the Nextjs Image component as below and use this component instead of Next Image:

import NextImage from "next/image";

const Image = ({...props }: any) => {
    const imageLoader = ({src, width, quality}: any) => {
        return `${src}?w=${width}&q=${quality || 75}`
    }

    return (
        <NextImage loader={imageLoader}  {...props} />
    )
  }

export default Image;

chaudhry avatar Jan 05 '24 18:01 chaudhry

I believe I am having a similar issue. I have cloudflare DNS in front of my DO server. I am using remote images from firestorage and passing the src to next/image. If I build and start nextjs locally these work fine, however as soon as I deploy to my DO server, the images return a 400 coming from cloudflare with the error The requested resource is not a valid Image

I tried using the unoptimized flag on the next/image component and this renders the image fine, since it uses the firestorage url directly.

Has anyone experienced this issue?

SilvanTheuma avatar Jan 26 '24 12:01 SilvanTheuma

Alternatively, you can set up custom loader via next.config.mjs file to use Image component directly. Example: https://github.com/t18n/next-cdn-image/blob/main/next.config.mjs#L3-L8

t18n avatar Jun 05 '24 21:06 t18n

Any working solution for this ? As it works fine on localhost. On my docker setup the images throws 404 error PS: I tried copying next config to docker as well I am using assets.example.in to serve the images via cdn

      domains: ["assets.example.in","www.example.in"],
      minimumCacheTTL: 60,
      dangerouslyAllowSVG: true,
     remotePatterns: [
        {
          protocol: 'https',
          hostname: 'assets.example.in',
          port: '',
          pathname: '/**',
        },
        {
          protocol: 'https',
          hostname: 'www.example.in',
          port: '',
          pathname: '/**',
        },
      ]

thinkingmonk avatar Jun 07 '24 08:06 thinkingmonk