Rehber: Vue.js Optimization
Vue.js, modern web uygulamaları geliştirmek için sunduğu esneklik ve performansla son yıllarda ciddi bir popülarite kazandı. Ancak her framework'te olduğu gibi, Vue'nun gücünü tam anlamıyla kullanabilmek için uygulamanızın performansını doğru şekilde optimize etmeniz gerekir. Küçük bir projede fark etmediğiniz yavaşlamalar, uygulamanız büyüdükçe ciddi kullanıcı deneyimi sorunlarına dönüşebilir.
Bu rehberde, Vue.js uygulamalarınızı hem geliştirme hem de üretim aşamasında nasıl hızlandırabileceğinizi, gerçek dünya senaryoları üzerinden ele alacağız. İster Vue 2 ister Vue 3 kullanıyor olun, burada paylaşılan tekniklerin büyük çoğunluğu işinize yarayacak.
Neden Vue.js Optimizasyonu Kritik?
Kullanıcıların bir web sitesinde geçirdiği ilk birkaç saniye, o sitenin kaderini belirliyor. Google'ın araştırmalarına göre, sayfa yüklenme süresi 3 saniyeyi aştığında mobil kullanıcıların %53'ü siteyi terk ediyor. Vue gibi reaktif bir framework kullanıyorsanız, bu süreyi doğrudan etkileyen faktörler var:
- Bundle boyutu: Gereksiz kod yüklenmesi
- Reaktivite maliyeti: Aşırı watcher ve computed kullanımı
- Render performansı: Gereksiz DOM güncellemeleri
- Bellek sızıntıları: Temizlenmeyen event listener'lar ve referanslar
Bu sorunları erken aşamada çözmek, sonradan refactor etmekten çok daha kolaydır.
1. Lazy Loading ve Code Splitting
Uygulamanızın tamamını tek bir bundle halinde yüklemek, özellikle büyük projelerde ciddi bir darboğaz oluşturur. Vue Router ile route bazlı lazy loading yapmak, kullanıcıya sadece ihtiyacı olan kodu göndermenizi sağlar.
// router/index.js
const routes = [
{
path: '/dashboard',
component: () => import('@/views/Dashboard.vue')
},
{
path: '/settings',
component: () => import('@/views/Settings.vue')
}
]
Bu basit değişiklik, ilk yükleme süresini ciddi ölçüde düşürebilir. Ayrıca büyük bileşenleri de dinamik olarak yükleyebilirsiniz:
<script setup>
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() =>
import('@/components/HeavyChart.vue')
)
</script>
İpucu: Webpack kullanıyorsanız webpackChunkName yorumuyla chunk'ları isimlendirerek hata ayıklamayı kolaylaştırabilirsiniz.
2. v-if ve v-show Arasındaki Doğru Tercih
Bu iki direktif sıkça karıştırılır ama performans açısından kritik farkları vardır:
- v-if: DOM'dan elementi tamamen kaldırır. İlk render maliyeti düşük, toggle maliyeti yüksektir.
- v-show: CSS
displayözelliğiyle gizler. İlk render maliyeti yüksek, toggle maliyeti düşüktür.
Karar kriteri: Bir element sık sık açılıp kapanıyorsa v-show, nadiren görünüyorsa v-if kullanın.
3. Computed vs Method: Doğru Kullanım
Vue'da computed özellikleri, bağımlılıkları değişmediği sürece cache'lenir. method ise her render'da yeniden çalışır.
<template>
<!-- Kötü: Her render'da yeniden hesaplanır -->
<div>{{ calculateTotal() }}</div>
<!-- İyi: Bağımlılıklar değişmedikçe cache'den gelir -->
<div>{{ total }}</div>
</template>
<script setup>
import { computed } from 'vue'
const total = computed(() => {
return items.value.reduce((sum, item) => sum + item.price, 0)
})
</script>
Liste render eden template'lerde method çağrısı yapmak, özellikle büyük listelerde ciddi performans kaybına yol açar.
4. v-for ile Key Kullanımı
v-for kullanırken :key vermek zorunlu değildir ama performans için kritiktir. Doğru key kullanımı, Vue'nun sanal DOM diff algoritmasının minimum DOM manipülasyonu yapmasını sağlar.
<!-- Kötü: index kullanımı -->
<li v-for="(item, index) in items" :key="index">
<!-- İyi: benzersiz ve stabil bir id -->
<li v-for="item in items" :key="item.id">
Index kullanmak, listede sıralama veya silme işlemleri yaptığınızda Vue'nun yanlış elemanları güncellemesine yol açar. Bu da hem performans hem de bug riski demektir.
5. v-once ve v-memo Direktifleri
Statik içerikler için v-once, Vue'ya "bunu bir kez render et, bir daha dokunma" der:
<template>
<header v-once>
<h1>{{ siteTitle }}</h1>
<p>{{ siteDescription }}</p>
</header>
</template>
Vue 3.2 ile gelen v-memo ise daha granüler bir kontrol sağlar. Belirli bağımlılıklar değişmediği sürece alt ağacı yeniden render etmez:
<div v-memo="[user.id, user.status]">
<!-- Sadece user.id veya user.status değiştiğinde yeniden render edilir -->
</div>
6. Watch ve WatchEffect Kullanımında Dikkat Edilmesi Gerekenler
Reaktivite harika bir şey ama her watch bir maliyettir. Özellikle derin (deep: true) izleme, büyük nesnelerde ciddi performans sorunlarına yol açar.
- Zorunlu olmadıkça
deep: truekullanmayın watchEffectyerine mümkünsecomputedtercih edin- İzleme işlemini
onUnmountedveyaonBeforeUnmount'ta temizleyin
import { watch, onBeforeUnmount } from 'vue'
const stop = watch(source, callback)
onBeforeUnmount(() => stop())
7. Bellek Sızıntılarını Önleme
Uzun ömürlü uygulamalarda bellek sızıntıları sessiz katillerdir. Vue'da sık karşılaşılan sızıntı kaynakları:
- Temizlenmeyen
setInterval/setTimeout - Kaldırılmayan global event listener'lar
- Kapatılmayan WebSocket bağlantıları
- Büyük veri yapılarının referanslarının tutulması
import { onMounted, onBeforeUnmount } from 'vue'
onMounted(() => {
window.addEventListener('resize', handleResize)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
})
8. Production Build Optimizasyonları
Geliştirme ortamında her şey harika görünebilir ama production'da asıl fark ortaya çıkar:
- Tree shaking: Kullanılmayan kodun bundle'dan çıkarılması
- Minification: Terser veya esbuild ile kod küçültme
- Compression: Brotli veya Gzip ile transfer boyutunu düşürme
- CDN kullanımı: Statik asset'leri edge'e taşıma
Vite kullanıyorsanız build.rollupOptions ile chunk stratejinizi özelleştirebilirsiniz:
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
charts: ['chart.js']
}
}
}
}
}
9. Görsel ve Asset Optimizasyonu
JavaScript optimizasyonu kadar görseller de kritik. Çoğu sitede toplam sayfa ağırlığının %60'ından fazlası görsellerden oluşur.
- WebP veya AVIF formatlarını tercih edin
loading="lazy"ile görselleri erteleyin- Responsive görseller için
srcsetkullanın - SVG ikonları sprite haline getirin
<img
src="hero.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w"
loading="lazy"
alt="Hero görseli"
/>
10. Sanal Listeleme (Virtual Scrolling)
Yüzlerce veya binlerce satır render eden listeler, tarayıcıyı felç edebilir. vue-virtual-scroller veya vue-virtual-scroll-grid gibi kütüphaneler, sadece görünür alandaki elemanları render eder.
<RecycleScroller
:items="items"
:item-size="50"
key-field="id"
>
<template #default="{ item }">
<div>{{ item.name }}</div>
</template>
</RecycleScroller>
Bu teknik, 10.000 satırlık bir tabloyu bile akıcı hale getirebilir.
11. Vue DevTools ile Profiling
Optimizasyon yapmadan önce ölçüm yapmak şart. Vue DevTools'un Performance sekmesi, hangi bileşenin ne kadar sürede render edildiğini, kaç kez güncellendiğini gösterir.
Dikkat etmeniz gereken sinyaller:
- 16ms'den uzun süren render'lar (60 FPS hedefi)
- Gereksiz yere yeniden render edilen bileşenler
- Çok sık tetiklenen reaktivite
12. SSR ve SSG Değerlendirmesi
Uygulamanız SEO veya ilk yükleme hızı açısından kritikse, SPA yerine Nuxt gibi bir çözümle SSR (Server-Side Rendering) veya SSG (Static Site Generation) tercih edebilirsiniz. Bu, ilk anlamlı boyama (FCP) süresini ciddi ölçüde düşürür.
Ancak SSR her proje için doğru cevap değildir. Etkileşim yoğun, kimlik doğrulama gerektiren uygulamalarda SPA hâlâ mantıklı olabilir.
Sonuç
Vue.js optimizasyonu tek seferlik bir iş değil, sürekli bir alışkanlıktır. Yukarıdaki tekniklerin çoğu uygulama kodunuza birkaç satır eklemekle başlar ama etkisi uzun vadede katlanarak büyür.
Özetlemek gerekirse:
- Ölçün, sonra optimize edin — DevTools olmadan tahminle ilerlemeyin
- Lazy loading ve code splitting ile başlayın
- Reaktiviteyi bilinçli kullanın — computed, watch ve v-memo'yu doğru yerde tercih edin
- Bellek sızıntılarını önleyin — temizlik alışkanlık haline gelsin
- Production build ve asset optimizasyonunu ihmal etmeyin
Küçük iyileştirmelerin birikimi, kullanıcılarınızın hissettiği hızda büyük farklar yaratır. Unutmayın: En hızlı kod, hiç çalıştırılmayan koddur. Gereksiz olanı silin, gerekli olanı optimize edin.