Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorunu ve bulduğum temiz çözümü paylaşmak istiyorum. Next.js projemde, sayfa performansını artırmak için büyük component'ları
ile lazy load etmeye başlamıştım. Ancak, component yüklenirken ekranda anlık bir boşluk (layout shift) veya hiçbir şey gözükmemesi kullanıcı deneyimini berbat ediyordu. İlk gördüğümde "Bu neyin kafası ya?" demiştim. Standart loading spinner'lar da bu duruma uygun değildi, çünkü component'ın kaplayacağı alanın boyutunu ve şeklini belli etmiyorlardı. İşte benim kullandığım, hem kullanıcıyı hem de SEO'yu düşünen kusursuz skeleton çözümü.
Sorun: Dynamic Import'ta Hayalet Component'lar
`next/dynamic` default olarak bir `loading...` string'i veya basit bir spinner component'ı kabul ediyor. Ama bu, yüklenecek olan gerçek component'ın layout'unu taklit etmiyor. Kullanıcıya "burada bir şey geliyor" hissi vermek ve sayfanın sabit durmasını sağlamak için, loading prop'una bir skeleton component'ı geçmemiz gerekiyor. Ancak bu skeleton'ın, lazy component ile tamamen aynı yükseklik, genişlik ve temel yapıya sahip olması şart.
Çözüm: NextDynamicWithSkeleton Factory'm
Bu sorunu her dynamic import için tekrar tekrar çözmek yerine, kendime küçük bir factory fonksiyonu yazdım. Bu fonksiyon, lazy component'ı ve onun skeleton'ını alıp, kusursuz bir dynamic component döndürüyor.
Skeleton Component'ımı Nasıl Tasarladım?
Skeleton'ın sadece gri kutulardan ibaret olmaması için biraz CSS sihri kullandım. Anahtar nokta, background-gradient animasyonu. Bu, içeriğin yatayda yüklendiği hissini veriyor ve çok daha profesyonel görünüyor.
Kullanımı: Temiz ve Tek Satır
Artık her şey hazır! Dynamic component'ımı oluşturmak ve kullanmak inanılmaz basit ve temiz hale geldi.
Sonuç olarak, bu yöntemle kullanıcılarım artık anlık boşluklar veya garip sıçramalar yaşamıyor. Sayfa layout'u ilk andan itibaren sabit kalıyor ve yükleme belirgin, şık bir şekilde gerçekleşiyor. Hem Lighthouse performans skorlarım arttı hem de kullanıcı geri bildirimleri çok olumlu yönde değişti.
Siz Next.js'te lazy loading için nasıl bir yöntem izliyorsunuz? Benim bu factory fonksiyonum işinizi görür mü, yoksa sizin daha farklı bir skeleton taktiğiniz var mı? Yorumlarda buluşalım!
JavaScript:
next/dynamic
`next/dynamic` default olarak bir `loading...` string'i veya basit bir spinner component'ı kabul ediyor. Ama bu, yüklenecek olan gerçek component'ın layout'unu taklit etmiyor. Kullanıcıya "burada bir şey geliyor" hissi vermek ve sayfanın sabit durmasını sağlamak için, loading prop'una bir skeleton component'ı geçmemiz gerekiyor. Ancak bu skeleton'ın, lazy component ile tamamen aynı yükseklik, genişlik ve temel yapıya sahip olması şart.
Bu sorunu her dynamic import için tekrar tekrar çözmek yerine, kendime küçük bir factory fonksiyonu yazdım. Bu fonksiyon, lazy component'ı ve onun skeleton'ını alıp, kusursuz bir dynamic component döndürüyor.
JavaScript:
// utils/nextDynamicWithSkeleton.js
import dynamic from 'next/dynamic';
/
@param {React.ComponentType} componentImport - Dinamik import fonksiyonu (() => import('./Component'))
@param {React.ComponentType} SkeletonComponent - Skeleton UI Component'ı
@param {object} dynamicOptions - next/dynamic'e ait ek options'lar (ssr: false gibi)
/
export function createDynamicComponent(componentImport, SkeletonComponent, dynamicOptions = {}) {
return dynamic(componentImport, {
loading: () => <SkeletonComponent />,
...dynamicOptions,
});
}
Skeleton'ın sadece gri kutulardan ibaret olmaması için biraz CSS sihri kullandım. Anahtar nokta, background-gradient animasyonu. Bu, içeriğin yatayda yüklendiği hissini veriyor ve çok daha profesyonel görünüyor.
JavaScript:
// components/skeletons/ProductCardSkeleton.jsx
import styles from './ProductCardSkeleton.module.css';
const ProductCardSkeleton = () => {
return (
<div className={styles.skeletonCard}>
<div className={styles.skeletonImage}></div>
<div className={styles.skeletonContent}>
<div className={styles.skeletonTitle}></div>
<div className={styles.skeletonText}></div>
<div className={styles.skeletonText} style={{ width: '60%' }}></div>
<div className={styles.skeletonButton}></div>
</div>
</div>
);
};
export default ProductCardSkeleton;
CSS:
/ components/skeletons/ProductCardSkeleton.module.css /
.skeletonCard {
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 1rem;
background-color: white;
/ Gerçek ProductCard ile AYNI yükseklik/genişlik değerleri /
width: 320px;
height: 400px;
}
.skeletonImage,
.skeletonTitle,
.skeletonText,
.skeletonButton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: 4px;
}
.skeletonImage {
height: 180px;
margin-bottom: 1rem;
}
.skeletonTitle {
height: 24px;
width: 80%;
margin-bottom: 0.75rem;
}
.skeletonText {
height: 16px;
width: 90%;
margin-bottom: 0.5rem;
}
.skeletonButton {
height: 40px;
width: 120px;
margin-top: 1rem;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
Artık her şey hazır! Dynamic component'ımı oluşturmak ve kullanmak inanılmaz basit ve temiz hale geldi.
JavaScript:
// pages/index.js
import { createDynamicComponent } from '../utils/nextDynamicWithSkeleton';
import ProductCardSkeleton from '../components/skeletons/ProductCardSkeleton';
// Tek satırda dynamic component oluşturma
const ProductCard = createDynamicComponent(
() => import('../components/products/ProductCard'),
ProductCardSkeleton,
{ ssr: false } // İsteğe bağlı ek next/dynamic ayarı
);
export default function HomePage() {
return (
<div>
<h1>Ürünlerimiz</h1>
{/ ProductCard artık yüklenirken mükemmel bir skeleton gösteriyor /}
<ProductCard productId={123} />
</div>
);
}
Sonuç olarak, bu yöntemle kullanıcılarım artık anlık boşluklar veya garip sıçramalar yaşamıyor. Sayfa layout'u ilk andan itibaren sabit kalıyor ve yükleme belirgin, şık bir şekilde gerçekleşiyor. Hem Lighthouse performans skorlarım arttı hem de kullanıcı geri bildirimleri çok olumlu yönde değişti.
Siz Next.js'te lazy loading için nasıl bir yöntem izliyorsunuz? Benim bu factory fonksiyonum işinizi görür mü, yoksa sizin daha farklı bir skeleton taktiğiniz var mı? Yorumlarda buluşalım!