Dynamic Import Nedir? Ne Zaman Kullanılmalı?
Aynı modülü herkes için ilk pakete koymak çoğu projede alışkanlık haline gelir. Sonra ekip paketin büyüdüğünü fark eder ve çözüm olarak “dinamik import yapalım” der. Bu karar bazen çok işe yarar, bazen de yalnızca beklemeyi başka bir ana taşır. Dynamic import, kodu küçültmekten önce yüklenme zamanını değiştirme kararıdır. Bu fark anlaşılmadan yapılan geçişler performans kazancı kadar yeni gecikme de üretebilir.
Modern frontend geliştirmede neredeyse her modülü "main chunk" içine yığmak, küçük başlayan projelerin zamanla ağırlaşmasının en yaygın yollarından biridir. Sonradan paket büyüklüğü fark edilip çözüm olarak "Dynamic import ile bileşenleri bölelim" dendiğinde, sorun bazen çözülmek yerine başka bir ana ötelenir. Dinamik import yalnızca kod hacmini daraltmaz; asıl görevi yüklenme zamanını değiştirmektir. Modüllerin bağlamı doğru okunmadan yapılan bir erteleme, sayfayı hafifletmek yerine etkileşim anında yeni takılmalar üretebilir.
Sayfayı açan her kullanıcı aynı modüle muhtaç değildir. Sadece %10'luk bir kesimin tıklayacağı karmaşık hesaplama paneli veya blog okuyan ziyaretçinin tıklama ihtimali düşük olan zengin medya yükleyicisi neden ilk açılış saniyesine (initial load) iştirak etsin? Dynamic import, bu yükleri ihtiyaç duyulduğu saniyeye kadar bir kenarda tutan kontrollü bir teslimat anahtarıdır.
Mimaride bu hamle, code splitting yeteneğinin en operasyonel yüzüdür. Derleyici paketi böler; ancak asıl sınav, bölünen modülün tetiklenme koşuludur. Sözdizimini (syntax) değiştirmek her şeyi halletmez; ağ trafiğiyle, cihazın hafıza temizliğiyle ve JavaScript'in o anki yorumlama maliyetiyle doğrudan bir donanım pazarlığı yaparsınız.
Dinamik bölme neden yalnızca sözdizimi kararı değildir?
Klasik statik import ile çağrılan bağımlılık, uygulamanın kritik yükleme zincirine girmeye mecburdur. Halbuki Dynamic import, bir fonksiyonun veya UI bileşeninin indirilmesini koşullu bir Promise olarak rezerve eder. Modül ancak kullanıcı spesifik bir butona bastığında, modal belirdiğinde ya da Intersection Observer bir bileşeni yakaladığında devreye girer. Test raporlarındaki "First Load JS" rakamları hemen yarıya inebilir. Laboratuvardaki bu hile çoğu geliştiriciye çok cazip gelir.
Faturanın kesildiği yer burasıdır. Daha uygun gördünüz diye asıl modülü butona tıklanma anına ötelediğinizde, cihaz HTTP uyanmasını, resolve etmeyi ve ana iş parçacığında parçalamayı o en dar etkileşim aralığında yapmak zorunda kalır. Eğer kullanıcı o ikona bastıktan 400 milisaniye sonra hala menü ekranda değilse, o ilk açılışta kazandığınız hız skoru INP ve algısal metrikler nezdinde buharlaşır.
Bu sebeple asıl denge şu sorular etrafında şekillenir: Bölünen parça başta gelse ana sayfayı ne kadar boğar, sonradan gelse etkileşim anını ne kadar kilitler? Örneğin e-ticaret sitelerindeki gizli gelişmiş filtreler veya kullanıcı incelemeleri bölümü, ana hero resminin olduğu ilk saniyeden daha az değerlidir. Ancak ödeme butonunun arkasındaki stripe/iyzico kütüphaneleri paket ufalacak diye dynamic import'a itilirse sipariş anındaki yavaşlık anında sepet terklerine yansır.
Ertelenebilir ağırlıklar nasıl tespit edilir?
Doğru adayların profil analizi nettir: Ekranın kalan kısmını bloke etmeyen, ağır bağımlılık barındıran, herkesin tıklamak zorunda olmadığı alanlar hedeflenir. Dev grafik çizimciler (Chart.js vs), PDF çıktı oluşturucuları, ağır animasyon kütüphaneleri, gizli ayar menüleri ya da kapalı akordeon sekmelerindeki dev data yığınları dynamic import'a en yatkın malzemelerdir.
Ancak bundle analizi yaparken ilk göze çarpan her büyük kütüphaneyi ertelemek doğru olmaz. Örneğin haber sitesinde sayfanın altındaki yorum okuyucusu dinamik olarak çağrılabilirken, video odaklı bir eğitim platformunda video player modülü ertelenmemelidir. Optimizasyon, yalnızca boyutu değil ürünün ana görevini de korumalıdır.
Tıklama anında blokaj yaratmamak için alınan tedbirler
Optimizasyonun en zor yan etkisi, kodu hafifletilen modülün tam çağırılma anında kullanıcının fareyle boş ekrana bakmasıdır. Hiçbir reaksiyon sunmayan bir arayüzde 300 ms geç yüklenen JavaScript, cihaz kitlenmiş hissiyatı verir. Dosyayı böldüyseniz, o yüklenme boşluğunu ara yüz (UI) geri bildirimleriyle doldurma zorunluluğunuz doğar.
Bordro mantığı basittir: Kod inmeden önce loader'ı yak, kodu indir, komponenti mount et, loader'ı söndür. Veya daha ileri seviyesi; modülü kullanıcının tam tıklama anında değil, imlecin hedefe yaklaşması (hover) anında pre-import etmektir.
// Klasik ve riskli yaklaşım
button.addEventListener('click', async () => {
const { openChart } = await import('./heavy-chart.js');
openChart(); // İndirme yavaşsa kullanıcı tıklayıp sessizce bekler
});
// Güvenli ve destekleyici yaklaşım
button.addEventListener('mouseenter', () => {
// İmleç yaklaşırken arkaplanda gizlice indirmeye başlanır
import('./heavy-chart.js');
});
button.addEventListener('click', async () => {
button.classList.add('is-processing'); // Skeleton / Loader göster
const { openChart } = await import('./heavy-chart.js');
openChart();
button.classList.remove('is-processing');
});
Asenkron modül indirme taktikleri bu ince hover/focus numaralarıyla birleştirilmediği sürece, optimizasyon sadece teknik ekibin zihnindeki bir yama olarak kalacaktır. 3G gibi zayıf bağlantılı senaryolar, dynamic import'un "Tıklayınca gelir" diyenleri avladığı asıl tuzaklardır.
Her rota ve ufak komponent bölünmemelidir
React/Vue ekosistemlerinde her küçük yardımcıyı ve ekran altı barını React.lazy() veya benzeri sarmallarla bölmek modern bir takıntıya dönüşebilir. Ufacık bir 15 KB modülü ayırmak, onu HTTP üstünden yeni bir istek fazına sokmak demektir. Tarayıcı o yeni bağlantıyı açarken, TCP handshake maliyeti zaten kazandığınız 15 KB ağ tasarrufunun getirisini yok eder.
Kritik navigasyon, erişilebilirlik ikonları veya sitenin kurumsal renk/font temaları gibi temel inşalar ilk pakette çivilenmiş halde durmalıdır. Dynamic import oynamaları nadir açılan 200 KB'lık yardımcı modüllerin işidir; sayfaya her girildiğinde ilk sahnede kesinlikle tetiklenecek modüllerin değil. Eğer bir kütüphane büyük ancak her kullanıcının anlık etkileşime sokacağı bir demirbaş ise; çözüm kodu ertelemek değil, tree shaking ve alternatif kütüphane incelemeleriyle boyutu küçültmektir.
Bağlantı ve önbellek pürüzleri
Her dinamik bağlantı ekstra bir Request (istek) anlamına gelir. Mobil ağ şartları yavaşken sonradan tetiklenen bir chunk, kullanıcıyı ekranda dondurabilir. Elbette ikinci ziyarette tarayıcı önbelleğinden o dosya hızlıca çekildiğinde her şey sorunsuz görünebilir. Ancak optimizasyon, o "ikinci şans" için değil, her kullanıcının yaşadığı soğuk açılış (cold start) için yapılmalıdır.
Altyapınızda sunucu gecikmeleri (TTFB) mevcutsa, sonradan inen modüller sunucunun yavaş cevap verme süreleriyle tekrar çarpışacağından sistem gerçekten iyileşmez; yalnızca sorunun yeri değişmiş olur. Erken çözülmesi gereken unsurları sonraya, sonra gelebilecek yükleri ise ilk açılışa yığmak mimariyi daha kırılgan hale getirir.
SSR ve dağıtım anındaki hatalar da hesaba katılmalıdır
Dynamic import kararları yalnızca ilk yük ve tıklama süresi üzerinden okunmamalıdır. Sunucu tarafı render edilen yapılarda, kullanıcı HTML iskeletini çok erken görebilir; fakat kritik bir etkileşim parçası sonradan indirildiği için hydration anında boşluk oluşabilir. Özellikle menü açıcılar, arama kutusu davranışları, sepet düğmeleri veya erişilebilirlik için zorunlu etkileşimler dinamik parçaya fazla bağımlı bırakılırsa sayfa görünür ama işlevsiz hissedilir. Bu da laboratuvar skorunda değil, gerçek kullanıcı davranışında sorun çıkarır.
Bir diğer görünmez risk sürüm geçişleridir. Üretim ortamında dosya adları hash ile değişiyorsa, kullanıcı açık sekmede eski HTML ile dolaşırken yeni deploy devreye girebilir. O anda dinamik import ile çağrılan parça artık sunucuda eski isimle bulunmuyorsa ChunkLoadError benzeri hatalar doğar. Kullanıcı tıklar, modül gelmez ve arayüz sessizce kırılır. Bu yüzden ağır modülleri ayırırken yalnızca performans değil, hata yakalama ve tekrar deneme stratejisi de düşünülmelidir.
Pratik çözüm, kritik etkileşimlerde sessiz başarısızlığa izin vermemektir. Dinamik modül yüklenemezse kullanıcıya yeniden deneme yolu, küçük bir geri bildirim katmanı veya kontrollü tam yenileme akışı sunulmalıdır. Aynı şekilde gerçekten temel olan bileşenleri, örneğin ana gezinme ya da oturum açma akışını, sadece paket küçülsün diye sonradan çağrılan yapıya çevirmek çoğu projede gereksiz risktir. Dynamic import en çok, gecikmesi tolere edilebilen fakat ilk paketi şişiren modüllerde değer üretir.
Sağlıklı karar için tek soru şudur: Bu modül geç gelirse kullanıcı işini sürdürebilir mi? Cevap hayırsa orada ya daha hafif bir kütüphane seçilmeli ya da modülün yalnızca bir bölümü ayrılmalıdır. Cevap evetse, o zaman dinamik yükleme gerçek bir mimari araç haline gelir. Böyle bakıldığında dynamic import, yalnızca dosya bölme tekniği değil; hata dayanıklılığı, dağıtım güvenliği ve etkileşim önceliği üzerine kurulu bir teslimat kararıdır.