Performans İçin Kod mu Bölünmeli, Sayfa mı Sadeleşmeli?
Performans sorunuyla karşılaşan bir ekibin ilk refleksi genellikle teknik bir optimizasyon arayışıdır: bundle'ı böl, lazy load ekle, gereksiz bağımlılığı çıkar. Bu araçlar değerlidir ve çoğu durumda işe yarar. Ancak bazı durumlarda asıl soru farklıdır: sayfa gerçekten bu kadar karmaşık olmak zorunda mı? Üretilen JavaScript yükünün bir kısmı optimize edilemez mi — daha doğrusu, hiç üretilmesi gerekmez miydi?
Kod bölme ile sayfa sadeleştirme birbirinin rakibi değildir. İkisi farklı soruları yanıtlar: kod bölme "bu kodu nasıl daha geç yüklerim" sorusunu yanıtlarken, sayfa sadeleştirme "bu kodu hiç yüklemek zorunda mı kalacağım" sorusunu sorar. Bu iki soruyu birlikte düşünmek, performans optimizasyonunu yalnızca teknik bir araç sorununa indirgemekten kurtarır.
Code splitting geciktirir, sadeleştirme ortadan kaldırır
Code splitting, bir uygulamanın JavaScript çıktısını daha küçük parçalara bölerek yalnızca ihtiyaç duyulduğunda yüklenmesini sağlar. Rota bazlı bölmede kullanıcı bir sayfaya gittiğinde o sayfanın kodu indirilir; henüz ziyaret edilmemiş rotaların kodu yüklenmez. Bu yaklaşım başlangıç yükünü düşürür ve ilk etkileşim süresini kısaltır.
Ancak kod bölme, yüklenmesi ertelenen kodu ortadan kaldırmaz. Kullanıcı o sayfaya gittiğinde kod yine yüklenir. Eğer bir sayfa gereksiz yere karmaşıksa — ihtiyaç duyulmayan bileşenler, hiç açılmayan modal'lar, görünmeyen sekmeler — bu bileşenler chunk'lara dağıtılmış olsa bile, kullanıcı onları tetiklediğinde yüklenirler. Kod bölme problemi dağıtır, çözmez.
Sayfa sadeleştirmesi ise kodu chunk'lara dağıtmak yerine tamamen kaldırır. Hiç render edilmeyen bir bileşen, hiç parse edilmez; hiç parse edilmeyen kod, main thread üzerinde hiç iş yaratmaz. Bu ayrım özellikle büyük ve nadir kullanılan özellikler için belirgindir: bir sayfaya %2 kullanıcının ulaştığı bir modal, code splitting ile ertelense de yüklenir; ayrı bir sayfaya taşınırsa yalnızca o %2 tarafından indirilir.
Sayfa mimarisi performans kararını erkene taşır
Sayfa yapısı tasarlanırken yapılan kararlar, sonradan yapılacak optimizasyonların tavanını belirler. Tek bir sayfaya sığdırılan çok sayıda özellik, ne kadar iyi code splitting uygulanırsa uygulansın belirli bir başlangıç yükü taşır. Bu yükü sıfıra indirmek mümkün değildir; ancak yükün bir kısmını başka sayfaya taşımak veya kaldırmak mümkündür.
Sayfa mimarisi kararları genellikle özellik planlaması sırasında alınır, performans optimizasyonu sırasında değil. Bu nedenle bu kararların performans maliyetini önceden değerlendirmek, sonradan pahalı refactor yapmaktan çok daha verimlidir. Bir özelliğin mevcut sayfaya eklenmesi ile ayrı bir rotaya taşınması arasındaki tercih, UX kararı olduğu kadar performans kararıdır da. Kullanıcı bu özelliğe ne sıklıkla ihtiyaç duyuyor? Her ziyarette mi, yoksa belirli koşullarda mı? Bu soru, özelliğin nerede yaşayacağını şekillendirir.
Mevcut sayfalarda bu kararları geriye dönük uygulamak güçtür. Bir özelliği ayrı bir rotaya taşımak navigasyon mantığını, URL yapısını ve bazen backend endpoint'lerini de etkiler. Bu nedenle sayfa sadeleştirmesi genellikle yeni özellikler için daha kolay uygulanır; mevcut büyük sayfalar için ise kademeli bir ayrıştırma stratejisi gerekir.
İkisi birlikte uygulandığında etki katlanır
Kod bölme ve sayfa sadeleştirme birbirini dışlamaz; tersine, birlikte uygulandıklarında her birinin tek başına sağlayabileceğinden daha büyük bir kazanım üretirler. Sadeleştirilmiş bir sayfa yapısında code splitting daha etkili çalışır: zaten kaldırılmış olan özellikler chunk'lara dağıtılmaz; kalan kod ise daha küçük ve daha iyi bölünmüş chunk'larla yönetilir.
Bir e-ticaret sitesini düşünelim: ürün detay sayfası giderek büyümüş, fotoğraf galerisi, 360 derece görüntüleyici, benzer ürünler, soru-cevap bölümü, video oynatıcı ve gelişmiş filtre paneli aynı sayfada yaşıyor. Kod bölme bu öğelerin bir kısmını lazy load edebilir; ancak sayfa her yüklendiğinde bu öğelerin tamamına ait altyapı kodu — state yönetimi, event listener'lar, API çağrıları — bir şekilde başlatılır. Bunların bir kısmını ayrı sayfalara veya açık talep üzerine yüklenen bağımsız widget'lara taşımak, code splitting'in tek başına sağlayamayacağı bir başlangıç maliyeti düşürümü üretir.
Dynamic import bu iki yaklaşımı birbirine bağlayan mekanizmadır. Bir özelliğin kod bloğunu kullanıcı talep ettiği anda asenkron olarak yüklemek, hem kod bölmenin erteleme kazancını hem de sadeleştirmenin "gereksiz yükleme yok" avantajını bir arada sunar. Kullanıcı hiç tetiklemezse, kod hiç inmez.
Kararı belirleyen iki soru vardır
Hangi yaklaşımın ne zaman uygun olduğunu belirleyen iki temel soru vardır. Birincisi: Bu özellik aynı kullanıcının aynı oturumda ihtiyaç duyacağı bir şey mi? Evet ise kod bölme yeterlidir; özellik başlangıçta yüklenmez, ihtiyaç duyulduğunda gelir. Hayır ise — ya da özellik çok nadir kullanılıyorsa — ayrı bir sayfaya veya tamamen isteğe bağlı bir modüle taşımak daha iyi bir seçenektir.
İkinci soru: Bu özelliğin kaldırılması veya taşınması UX akışını nasıl etkiler? Eğer kullanıcı bu özelliğe mevcut sayfa bağlamında ihtiyaç duyuyorsa — örneğin bir formun içindeki yardım paneli — ayrı sayfaya taşımak UX'i bozar ve getirisinden çok götürür. Eğer özellik yalnızca belirli bir kullanıcı türü için anlam taşıyorsa ve mevcut sayfa bağlamıyla zayıf bir ilişkisi varsa, taşımak hem UX'i hem de performansı iyileştirir.
Bu iki soruyu yeni özellik planlamasına sistematik olarak dahil etmek, performans maliyetini mimari kararlara entegre etmenin en pratik yoludur. PageSpeed Insights veya Lighthouse skoru düştükten sonra müdahale etmek yerine, özelliğin nereye yerleştirileceğine karar verirken performans boyutunu da masaya getirmek, optimizasyon yükünü önemli ölçüde azaltır.
Kod bölme performans araç kutusunun vazgeçilmez bir parçasıdır. Ancak araç kutusu yalnızca bu araçtan ibaret değildir; ve iyi bir yazılım geliştiricinin görevi, hangi aracın hangi soruyu yanıtladığını ayırt edebilmektir. Bazen en iyi optimizasyon, kodu nasıl böleceğimizi değil, neyi gerçekten sayfaya koyacağımızı yeniden sorgulamaktır. Bu sorgulama teknik bir karar olduğu kadar ürün ve tasarım kararıdır da; ve üretilen kazanım, yalnızca developer araçlarıyla elde edilebilecek olanın çok ötesine geçebilir. Performans, mühendisliğin tek başına çözdüğü değil; ürün, tasarım ve mühendisliğin birlikte sahiplendiği bir kalite boyutudur.
Sayfa sadeleştirmenin bir diğer boyutu, aynı içeriği farklı bir yapıda sunmaktır. Uzun ve karmaşık bir sayfa, içeriği çok sayıda alt sayfaya bölerek hem URL yapısını temizler hem de her sayfanın JavaScript ve CSS yükünü küçültür. Bu yaklaşım çok adımlı formlar, ayarlar sayfaları ve karmaşık dashboard'lar için özellikle uygulanabilirdir. Kullanıcı tüm adımları görmek yerine yalnızca bulunduğu adımın içeriğini yükler; bu da LCP ve INP değerlerine doğrudan yansır. Kimi zaman UX açısından da daha temiz bir sonuç üretir: odaklanmış bir sayfa, her şeyin bir arada olduğu karmaşık bir arayüzden çoğu kullanıcı için daha anlaşılırdır.
Performans optimizasyonunu yalnızca teknik bir problem olarak çerçevelemek, çözüm alanını daraltır. Code splitting bir bundler konfigürasyonu, lazy loading bir HTML niteliği, önbellekleme bir sunucu başlığıdır — bunlar yazılım geliştiricinin araçlarıdır. Ancak sayfa yapısı, özellik önceliği ve kullanıcı akışı, ürün ve tasarım kararlarıdır. Bu iki alanın ortak bir optimizasyon diliyle konuşması — performansın bir ürün gereksinimi olarak planlanması — teknik araçların tek başına sağlayamayacağı sonuçları mümkün kılar. Bir sayfanın daha hızlı olmasının en etkili yolu, bazen o sayfanın daha az şey yapmasından geçer.
Teknik optimizasyonların bir diğer sınırı, üçüncü parti scriptlerle ilgilidir. Bir sayfada çalışan analitik, canlı destek, A/B test veya reklam scriptleri, o sayfanın karmaşıklığına katılır. Code splitting bu scriptlerin yükünü azaltmaz; bunlar genellikle doğrudan head'den veya tag manager üzerinden yüklenir. Sayfa sadeleştirmesi ise hangi sayfaların bu scriptlere ihtiyaç duyduğunu sorgulamayı mümkün kılar: analitik her sayfada zorunlu mu, yoksa yalnızca belirli dönüşüm sayfalarında mı anlam taşır? Canlı destek widget'ı yalnızca destek sayfasında mı olmalı? Bu soruların cevapları, kod bölmenin erişemeyeceği bir yük azaltımı potansiyeli taşır.
Mimari yalınlık ile özellik zenginliği arasındaki denge her zaman net değildir. Kullanıcıların değer bulduğu özellikler performans maliyeti taşısa da kaldırılmamalıdır. Önemli olan, bu dengeyi bilinçli olarak kurmaktır: hangi özellik gerçekten kullanılıyor, hangi sayfa bağlamında anlam taşıyor ve hangi alternatif yapı aynı değeri daha az yükle sunabilir? Bu soruları sormak, optimizasyon sürecini araç seçiminden önce mimari düşünmeyle başlatır.
Gerçek kullanıcı verisi, bu kararları nesnel bir zeminde değerlendirmenin en sağlam yoludur. Hangi sayfalar en uzun süre yükleniyor, hangi özellikler en çok tetikleniyor, hangi akışlarda kullanıcılar en çok bekliyor? Bu sorular, hem neyin optimize edileceğini hem de neyin sadeleştirileceğini belirler. Sayfa basitleştirme kararını sezgiye değil, kullanım verilerine dayandırmak, hem yanlış kaldırma riskini azaltır hem de en yüksek etkiyi yaratacak değişikliğin doğru seçilmesini sağlar.