Astro ile İçerik Sitelerinde Bundle Boyutunu Sıfıra Yaklaştırmak
Astro, içerik sitelerinde varsayılan olarak sıfır JavaScript gönderir. Island mimarisi ve client: direktifleri sayesinde React, Vue veya Svelte bileşenleri yalnızca gerçekten gerektiğinde tarayıcıda çalışır; sayfanın geri kalanı saf HTML olarak kalır.
Bir içerik sitesi yayına aldığınızda, sayfa başına düşen JavaScript miktarı hem tarayıcı işleme süresini hem de kullanıcının sayfayla etkileşime geçebildiği anı doğrudan etkiler. Blog yazıları, dokümantasyon sayfaları, pazarlama siteleri - bunların büyük bölümü statik metindir; herhangi bir etkileşim gerektirmez. Ama klasik bir SPA çerçevesiyle inşa edildiğinde, tarayıcı önce yüzlerce kilobayt JavaScript paketini indirir, parse eder, çalıştırır, ardından sayfayı render eder. Astro bu denklemi tersine çevirir.
Astro'nun temel iddiası basittir: HTML üret, JS gönderme. Çerçeve bileşenleri derleme aşamasında statik HTML'e dönüştürülür; tarayıcıya herhangi bir runtime kodu ulaşmaz. Sayfada gerçekten etkileşim gereken bir bileşen varsa, o bileşene özel bir karar verilir: ne zaman, hangi koşulda yüklensin?
Bu yaklaşım, island mimarisi (island architecture) olarak da bilinir. Sayfanın çoğu statik "okyanus" iken, etkileşimli bileşenler birer "ada" gibi kendi hydration kurallarıyla yaşar. Sonuç, küçük bir paket değil - çoğu sayfa için sıfır paket olur.
Derleme Zamanında Gerçekte Ne Olur?
Astro bileşenleri (.astro uzantılı dosyalar) bilinçli olarak çift katmanlı çalışır. Ön madde bloğunda (frontmatter) yazılan her şey - veri çekme, import ifadeleri, değişken hesapları - yalnızca sunucu ya da derleme zamanında işlenir. Şablon bölümü ise düz HTML'e derlenir.
React, Vue veya Svelte bileşenini bir .astro dosyasına dahil ettiğinizde Astro iki seçenek sunar. Bileşene herhangi bir client:* direktifi vermezseniz, Astro o bileşeni yalnızca sunucu tarafında çalıştırır ve saf HTML çıktısı üretir. Tarayıcıya React runtime'ı, bileşen kodu veya event listener ulaşmaz. Bileşen içindeki useState, useEffect gibi hook'lar çalışmaz - ama zaten çalışmasına gerek yoktur, çünkü sonuç statik metindir.
astro build komutu tamamlandıktan sonra dist/ klasörüne bakmak aydınlatıcıdır. Direktifsiz bileşenlerle dolu bir blog sayfası için dist/ altındaki tek .js dosyası büyük ihtimalle Astro'nun kendi küçük client runtime'ıdır - birkaç kilobayt. HTML dosyaları, gömülü inline stiller ve statik varlıklar dışında hiçbir şey yoktur.
Island Mimarisi: Bileşen Başına Hydration Kararı
"Hydration" kavramı, statik HTML'in JavaScript ile canlandırılması anlamına gelir. Klasik SSR yaklaşımında tüm sayfa tek bir paket halinde hydrate edilir; kullanıcı sayfanın herhangi bir yerine tıklamadan önce tarayıcı bu kodu yüklemek ve çalıştırmak zorundadır.
Island mimarisinde bu karar bileşen düzeyine iner. Her bileşen kendi hydration zamanlamasını alır; sayfanın geri kalanı bunu beklemez. Navbar, hero bölümü, uzun bir makale gövdesi - bunların tümü statik HTML olarak gelir. Yorum formu, canlı arama kutusu veya sepet ikonu gibi bileşenler ise birer ada olarak çalışır.
Ada sayısı arttıkça paket boyutu büyür. Hangi bileşenin gerçekten etkileşim gerektirdiğine dikkatle bakmak gerekir. Bir dropdown menü açılıp kapanıyorsa, bunu CSS :focus-within veya details/summary ile çözmek mümkün olabilir. Kullanıcı verisi gösteriyorsa ve bu veri değişmiyorsa, statik HTML yeterlidir. Etkileşimi sorgulayın; gerekmiyorsa ada kurmayın.
client: Direktifleri ve Yükleme Zamanlaması
Astro beş direktif sunar; her biri farklı bir zamanlama ve öncelik sırası belirler.
client:load bileşeni sayfa yüklenmesiyle birlikte hemen hydrate eder. Kritik etkileşimler - açılışta kullanıcı girişi bekleyen bir form ya da anında tepki gerektiren bir arayüz öğesi - için uygundur. Hemen gerekmeyen her şeyi buraya koymak, ilk yükleme süresini gereksiz yere uzatır.
client:idle tarayıcı boşta kaldığında, yani requestIdleCallback tetiklendiğinde yükler. Sosyal paylaşım butonları, çerez bildirimi veya sayfa açılışında görünmese de sonunda kullanılabilecek ikincil özellikler buraya uygundur. Ana yükleme akışını bloklamaz.
client:visible bileşen görünür alana girene kadar bekler; IntersectionObserver kullanır. Uzun sayfalarda, özellikle footer yakınındaki bileşenler için doğru seçimdir. Kullanıcı oraya hiç inmezse bileşen hiç yüklenmez.
client:media bir CSS media query doğrulandığında yükler. Yalnızca mobilde gösterilen bir drawer menü, client:media="(max-width: 768px)" ile masaüstünde hiç yüklenmez; bu, büyük ekranlarda sıfır maliyet anlamına gelir.
client:only sunucu tarafında hiç render etmez; yalnızca tarayıcıda çalışır. SSR ile uyumsuz, tarayıcı API'lerine bağımlı bileşenler - örneğin window.localStorage veya canvas kullananlar - bu direktifle sorunsuz çalışır. Hydration sırasındaki uyumsuzluk hataları ortadan kalkar.
Seçim karmaşık değil. "Bu bileşen sayfa açılışında görünür mü?" Hayırsa client:idle veya client:visible. "Yalnızca belirli ekran boyutunda mı?" client:media. "Tarayıcıya özgü API kullanıyor mu?" client:only. Bunların hiçbiri değil ve gerçekten kritikse: client:load.
Birden Fazla Çerçeve Aynı Projede
Astro'nun dikkat çekici özelliklerinden biri, tek bir projede birden fazla bileşen çerçevesini bir arada kullanabilmesidir. React ile yazılmış bir yorum bileşeni, Vue ile yazılmış bir harita widget'ı ve Svelte ile yazılmış küçük bir sayaç aynı sayfada yan yana var olabilir.
Mevcut bir projeyi Astro'ya taşırken bu esneklik zaman kazandırır. Farklı takım üyelerinin farklı çerçevelerle yazdığı bileşenleri yeniden yazmak zorunda kalmadan aktarmak mümkün olur. Sıfırdan proje başlatıyorsanız, tek çerçeve seçmek daha az karmaşıklık getirir ve bakım yükünü azaltır.
Çerçeve karışımının bir bedeli vardır. Her çerçeve kendi runtime'ını beraberinde getirir: React ve ReactDOM yaklaşık 40-45 kB gzip, Vue core daha az, Svelte ise çok daha küçük bir runtime ile gelir. Birden fazla çerçeve kullandığınızda her birinin runtime'ı ayrı ayrı yüklenir; ada sayısı az bile olsa toplam paket büyür. İçerik ağırlıklı sitelerde Svelte tercih edilmesinin teknik gerekçesi büyük ölçüde bu boyut farkıdır.
Ne Zaman Bu Yaklaşım Ters Etki Yapar?
Astro her proje için doğru seçim değildir. Uygulama, statik içerikten çok etkileşimli arayüz üzerine kuruluysa - SaaS dashboard'ları, gerçek zamanlı işbirliği araçları, oyun arayüzleri - ada yaklaşımı tersine döner. Sayfanın büyük bölümü etkileşimliyse, bileşen başına direktif yazmak karmaşıklığı artırır; herhangi bir paket tasarrufu da sağlanmaz, çünkü neredeyse her bileşen zaten hydrate edilmektedir.
Durum yönetimi de bir sınır çizer. Birden fazla ada arasında paylaşılan global state doğrudan iletişim kuramaz; adalar birbirinden izole çalışır. Bu tasarım gereğidir - performansın kaynağı da budur - ama ilerleyen süreçte bir kısıtlama gibi hissettirebilir. Çözüm olarak Nano Stores gibi çerçeve-bağımsız durum yöneticileri kullanılır ya da state, sunucu tarafında URL veya cookie aracılığıyla taşınır.
Bir diğer senaryo, SSR modundaki Astro'dur. output: 'server' ile çalışıldığında sayfalar derleme zamanında değil istek zamanında render edilir; bu durumda performans profili değişir ve sıfır-JS iddiası statik çıktıdan farklı anlam taşır. Sunucu yanıt süresi, CDN cache stratejisi ve önbellek geçersizleştirme ayrıca planlanmalıdır.
Build Çıktısını Okumak
Teorik anlatımı doğrulamanın en kısa yolu build çıktısına bakmaktır. astro build --verbose komutu hangi sayfaların üretildiğini, hangi chunk'ların oluştuğunu ve her birinin boyutunu listeler.
client:load alan bir React bileşeni eklendiğinde dist/ altında iki yeni dosya belirir: React ve ReactDOM'un minifiye bundleları ile bileşenin kendi kodu. client:visible olan ikinci bir bileşen ayrı bir chunk üretir; tarayıcı bunu yalnızca kullanıcı o alana geldiğinde indirir. Adaların lazy yüklenmesi, ağ taleplerinin zamanlamasını DevTools Network sekmesinde net biçimde gösterir.
Bu çıktıyı düzenli aralıklarla gözden geçirmek, farkında olmadan eklenen ağır bağımlılıkları erken fark ettirir. Bir utility kütüphanesinin beklenen birkaç kilobayt yerine onlarca kilobayt getirdiği, yalnızca build çıktısına bakıldığında görünür hale gelir. İzleme alışkanlığı sonradan büyük sürprizleri engeller.
Statik Site ile Karma Mod Arasında Karar
Astro üç temel mod sunar: tam statik (output: 'static'), tam dinamik (output: 'server') ve karma (output: 'hybrid'). İçerik ağırlıklı sitelerde çoğu sayfa statik olabilirken, kullanıcıya özgü içerik - hesap paneli, ödeme akışı - sunucu tarafı render gerektirebilir.
Karma mod, sayfa başına karar vermeye olanak tanır. Statik kalmasını istediğiniz sayfaya export const prerender = true eklenince, o sayfa derleme zamanında HTML'e dönüşür. Dinamik olması gereken sayfa ise sunucu tarafında her istekte üretilir. Her ikisi de aynı Astro projesinde, aynı bileşen dosyaları paylaşılarak yönetilir.
İçerik sitelerinde en sık karşılaşılan senaryo şudur: binlerce blog yazısı statik, site içi arama dinamik, kullanıcı profil sayfası karma. Bu üçünü aynı çerçevede yönetmek, bakım maliyetini düşürür ve dağıtım karmaşıklığını azaltır. Hangi sayfanın nasıl davranacağı, dosyanın en üstündeki tek satır export ile belirlenir.
Astro'nun değer önerisi özellikle içerik sitelerinde netleşir: HTML zaten cevaptır ve JavaScript o cevabı gereksiz yere ağırlaştırır. Etkileşim gereken yerde direktifler bilinçli kararlar vermeyi sağlar; gereksiz yerde yük taşınmaz. Sıfır-JS iddiası bir tasarım hedefi değil, varsayılan davranıştır.
Araç nispeten yeni olduğundan bazı üçüncü taraf entegrasyonlar, SSR adaptörleri arasındaki farklar veya edge deployment senaryoları zaman zaman ek yapılandırma ister. Varsayılan davranış (etkileşim yoksa JavaScript göndermemek) tutarlı biçimde işler.
Sayfanın büyük bölümü statik içerik, küçük bölümü etkileşimse Astro'nun varsayılanı o profile oturur. Mevcut bir React veya Vue sitesini tamamen yeniden yazmak yerine, yeni bir alt sitede veya yeni sayfa grubunda ölçmek hem öğrenme eğrisini düşürür hem de kararı gerçek transfer boyutuna bağlar.