Slow loading of images on product page
rumfiske opened this issue · comments
Images are extremely slow to load on the product's page.
About 4-6 seconds to load from the server, as i can see from my network's tab. But after its cached it seems to be lightning fast.
"Components>product>gallery.tsx" file is a client component, so i dont get why it is so slow? What can i do?
My Gallery file
'use client';
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
import { GridTileImage } from 'components/grid/tile';
import { ProductVariant } from 'lib/shopify/types';
import { createUrl } from 'lib/utils';
import Image from 'next/image';
import Link from 'next/link';
import { usePathname, useSearchParams } from 'next/navigation';
export function Gallery({
images,
variants
}: {
images: { src: string; altText: string }[];
variants: ProductVariant[];
}) {
const pathname = usePathname();
const searchParams = useSearchParams();
const imageSearchParam = searchParams.get('image');
const imageIndex = imageSearchParam ? parseInt(imageSearchParam) : 0;
const nextSearchParams = new URLSearchParams(searchParams.toString());
const nextImageIndex = imageIndex + 1 < images.length ? imageIndex + 1 : 0;
nextSearchParams.set('image', nextImageIndex.toString());
const nextUrl = createUrl(pathname, nextSearchParams);
const previousSearchParams = new URLSearchParams(searchParams.toString());
const previousImageIndex = imageIndex === 0 ? images.length - 1 : imageIndex - 1;
previousSearchParams.set('image', previousImageIndex.toString());
const previousUrl = createUrl(pathname, previousSearchParams);
const buttonClassName =
'h-full px-6 transition-all ease-in-out hover:scale-110 hover:text-black dark:hover:text-white flex items-center justify-center';
//if there are variants, then the default variant is the first one
const defaultVariantId = variants.length ? variants[0]?.id : undefined;
// Extract the 'farve' parameter from the URL search parameters.
const selectedFarve = searchParams.get('farve');
// Find a variant where the 'Farve' option matches the 'farve' URL parameter.
let variant = variants.find((variant: ProductVariant) =>
variant.selectedOptions.some(
(option) =>
option.name.toLowerCase() === 'farve' &&
option.value.toLowerCase() === selectedFarve?.toLowerCase()
)
);
const selectedVariantId = variant?.id || defaultVariantId;
const filteredVariant = variants.filter((item) => item.id === selectedVariantId);
// console.log(images);
return (
<>
<div className="relative aspect-square h-full max-h-[550px] w-full overflow-hidden">
{images[imageIndex] && imageSearchParam ? (
<Image
className="h-full w-full object-contain opacity-0 transition-opacity duration-[2s] ease-in-out"
onLoad={(e: any) => {
e.target.classList.remove('opacity-0');
}}
fill
fetchPriority="high"
alt={images[imageIndex]?.altText as string}
src={images[imageIndex]?.src as string}
sizes="(min-width: 1024px) 66vw, 100vw"
priority={true}
/>
) : (
<Image
className="h-full w-full object-contain opacity-0 transition-opacity duration-[2s] ease-in-out"
onLoad={(e: any) => {
e.target.classList.remove('opacity-0');
}}
fill
fetchPriority="high"
alt={filteredVariant[0]?.title as string}
src={filteredVariant[0]?.image?.url as string}
priority={true}
/>
)}
{images.length > 1 ? (
<div className="absolute bottom-[15%] flex w-full justify-center">
<div className="mx-auto flex h-11 items-center rounded-full border border-white bg-neutral-50/80 text-neutral-500 backdrop-blur dark:border-black dark:bg-neutral-900/80">
<Link
prefetch
aria-label="Previous product image"
href={previousUrl}
className={buttonClassName}
scroll={false}
>
<ArrowLeftIcon className="h-5" />
</Link>
<div className="mx-1 h-6 w-px bg-neutral-500"></div>
<Link
prefetch
aria-label="Next product image"
href={nextUrl}
className={buttonClassName}
scroll={false}
>
<ArrowRightIcon className="h-5" />
</Link>
</div>
</div>
) : null}
</div>
{images.length > 1 ? (
<ul className="my-12 flex items-center justify-center gap-2 overflow-auto py-1 lg:mb-0">
{images.map((image, index) => {
const isActive = index === imageIndex && imageSearchParam ? true : false;
const imageSearchParams = new URLSearchParams(searchParams.toString());
imageSearchParams.set('image', index.toString());
return (
<li key={image.src} className="h-20 w-20">
<Link
prefetch
aria-label="Enlarge product image"
href={createUrl(pathname, imageSearchParams)}
scroll={false}
className="h-full w-full"
>
<GridTileImage
alt={image.altText}
src={image.src}
width={80}
height={80}
active={isActive}
/>
</Link>
</li>
);
})}
</ul>
) : null}
</>
);
}
Hey there, I cannot reproduce on https://demo.vercel.store/.
Do you have a deployed example where you are seeing them slow to load? It might be running slower on localhost because you're seeing the page first compile, then the image get optimized and cached, and then displayed.
Hey there, I cannot reproduce on https://demo.vercel.store/.
Do you have a deployed example where you are seeing them slow to load? It might be running slower on localhost because you're seeing the page first compile, then the image get optimized and cached, and then displayed.
Yes please see it on drommeriet.dk :)