Next.js Discord

Discord Forum

Slow image loading with Next.js, Vercel, Firebase Storage, and Cloudflare CDN

Answered
West African Crocodile posted this in #help-forum
Open in Discord
West African CrocodileOP
I am using Next.js for my web application, hosted on Vercel, and storing images in Firebase Storage. I'm displaying these images using the <Image/> component from Next.js and leveraging Cloudflare's CDN.

Occasionally, when accessing the application, the images take an extremely long time to load, and I see a "pending" status.
What could be causing this issue? Here are some details about my setup:
Next.js application
Hosted on Vercel
Images stored in Firebase Storage
Using <Image/> component from Next.js to display images
Cloudflare CDN is enabled

I've noticed that this problem doesn't occur consistently, but when it does, the image loading becomes very slow.
Any ideas on what might be causing this and how I can troubleshoot the issue? Any help or suggestions would be greatly appreciated!


The code looks like this
  <Image
    src={'/icon.webp'}
    alt={"alt"}
    fill
    style={{ objectFit: 'cover' }}
    priority={true}
  />
Answered by Arinji
since you didnt set a sizes property, even though the image box is of a max of 518px, your image is 1920*1920
View full answer

42 Replies

give it a size
if its an icon, im guessing you have a div around it with a certain size and the relative property? @West African Crocodile
West African CrocodileOP
@Arinji
I wrote "icons," but in reality, non-icons are also dynamically entered.
The size of the image is about 700 kb, and it will never exceed 700 kb.
West African CrocodileOP
I'm having problems with the url below.
I know it's not a good idea to share the url, but I'll just share the location of the problem.
https://twinarte.com/
found the issue
@West African Crocodile
thats the image you are fetching
since you didnt set a sizes property, even though the image box is of a max of 518px, your image is 1920*1920
Answer
hence until it gets cached, your image takes time to load
made sense i hope?
West African CrocodileOP
Thanks! I'm trying it out now.
That could definitely be a problem.
np, send me the image code with the sizes prop once done if its not working
West African CrocodileOP
 <div className='relative h-60 w-full'>
              <div className='relative h-60 w-full'>
                <Image
                  src={idea.imageUrl || '/icon.webp'}
                  alt={idea.title}
                  fill
                  style={{ objectFit: 'cover' }}
                  className='border-gray-200'
                  priority={true}
                />
              </div>
            </div>


I use tailwind css and code like this.
American Crow
Just to be sure: You did overwrite the <Image> component to use a custom (cloudflare cdn) loader,?
West African CrocodileOP
@American Crow
I don't know, because I haven't messed with the cloudfrare settings (others may have). But if it's caused by cloudfrare, where in the settings can I fix it?
American Crow
i'd assume you want the cloudflare cdn to do the image optimization which otherwise vercel would do:
e.g. choosing width & height or autoamtic .wepb or .avif format based on the brower support.
In order to get that you'll have to integrate a custom loader:
https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/
West African CrocodileOP
@American Crow
I didn't integrate a custom loader. This is one of the most likely causes! Thanks. I'll try to fix that.
American Crow
yea once you did you can use the Image component as usual:
    <Image
      loader={cloudflareLoader}
      src="/me.png"
      alt="Picture of the author"
      width={500}
      height={500}
    />

this would roughly translate into a request a url e.g. cdn.cloudflare.com/cdn-cgi/image/me.png?width=500&quality=80&format=webp and the cdn returns a image as requested
American Crow
yea just follow the inststurctions from cloudflare. you'll be fine (it's either global loader or custom loader)
@Arinji Btw quick note... You didn't add the sizes property
West African CrocodileOP
Thanks! I'll remember to fix this one too.
Also you cant do the cdn loader with vercel
Vercel has its own optimizations and image hosting systems
Also I wouldn't do it as well, cache revalidation would go out the window
So if you update the images.. cloudlfare won't know
@Arinji https://www.reddit.com/r/nextjs/s/P715EOAmFp
West African CrocodileOP
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'firebasestorage.googleapis.com',
      },
      {
        protocol: 'https',
        hostname: 'storage.googleapis.com',
      },
      {
        protocol: 'https',
        hostname: 'twinarte.com',
      },
    ],
    loader: 'custom',
    loaderFile: './imageLoader.js',
  },
...


const normalizeSrc = (src) => {
  return src.startsWith('/') ? src.slice(1) : src;
};

export default function cloudflareLoader({ src, width, quality }) {
  const params = [`width=${width}`];

  if (quality) {
    params.push(`quality=${quality}`);
  }

  const paramsString = params.join(',');

  if (src.startsWith('https://twinarte.com')) {
    return `https://twinarte.com/cdn-cgi/image/${paramsString}/${normalizeSrc(src.replace('https://twinarte.com', ''))}`;
  } else if (
    src.startsWith('https://firebasestorage.googleapis.com') ||
    src.startsWith('https://storage.googleapis.com')
  ) {
    return `${src}?${paramsString}`;
  } else {
    return `/cdn-cgi/image/${paramsString}/${normalizeSrc(src)}`;
  }
}


I'm trying to add imageLoader.js and see if I can get this to work with next-js-config, but I'm not sure if I'm doing it right.
No clue about custom loaders, never used it before since sizes with vercel is the best option
West African CrocodileOP
Indeed. As long as I'm using <Image/>, I think relying on vercel's image optimization is a good idea.
I'll try to edit the size down to something nice.
Just find what's the largest size, so for you check the width of the image at different breakpoints and then add them
Tailwind intellisence helps where you can see the min width and use that with the width values
@Arinji Tailwind intellisence helps where you can see the min width and use that with the width values
West African CrocodileOP
Thanks! I've sized the image appropriately for the production environment, about 640 * 640.
@Arinji so works now?
West African CrocodileOP
So far, no matter how many times I load it, it works.
Is it sometimes PENDING if the size is too large?
At any rate, it's working now, so thanks!
mark a solution if it helped you :D