Rehber: Vue.js Optimization
Vue.js, modern web uygulamaları geliştirmek için sunduğu esneklik ve performansla öne çıkan bir framework. Ancak uygulamanız büyüdükçe, kullanıcı sayınız arttıkça ve özellik setiniz genişledikçe, başlangıçta göz ardı edilen küçük detaylar ciddi performans sorunlarına dönüşebiliyor. Bu rehberde, Vue.js uygulamalarınızı hem geliştirme hem de çalışma zamanında nasıl optimize edebileceğinizi, gerçek dünya senaryolarıyla ele alacağız.
İster Vue 2, ister Vue 3 kullanıyor olun; temel prensipler büyük ölçüde aynı. Farklar ortaya çıktığında ise bunları ayrıca belirteceğim.
Neden Optimizasyon Önemli?
Kullanıcıların bir web uygulamasından beklentisi her geçen gün artıyor. 100 milisaniyelik bir gecikme bile dönüşüm oranlarını düşürebiliyor. Vue.js, reaktif sistem sayesinde geliştirici deneyimini harika bir seviyeye taşısa da, bu reaktivite yanlış kullanıldığında performansın en büyük düşmanı haline gelebiliyor.
Optimizasyonu üç ana başlıkta düşünebiliriz:
- Render performansı: Gereksiz DOM güncellemelerini önlemek
- Yükleme performansı: İlk açılış süresini kısaltmak, bundle boyutunu küçültmek
- Bellek ve kaynak yönetimi: Sızıntıları önlemek, gereksiz hesaplamaları ortadan kaldırmak
1. Reaktiviteyi Doğru Kullanmak
Vue'nun kalbi reaktivite. Ancak her şeyi reaktif yapmak, beraberinde gereksiz hesaplama yükü getiriyor.
ref ve reactive Arasındaki Farkı Bilin
Küçük, tekil değerler için ref kullanmak hem daha okunabilir hem de daha performanslıdır. Büyük, iç içe geçmiş nesneler için reactive tercih edilebilir; ancak bu durumda derin reaktivitenin maliyetini unutmayın.
// Basit ve hafif
const count = ref(0)
// Derin reaktivite — dikkatli kullanın
const state = reactive({
user: { profile: { settings: { theme: 'dark' } } }
})
shallowRef ve shallowReactive ile Derin Takibi Kapatın
Eğer bir nesnenin içindeki değişiklikleri takip etmenize gerek yoksa, sığ reaktivite kullanmak ciddi bir performans kazancı sağlar. Özellikle büyük listeler veya üçüncü parti kütüphane nesneleriyle çalışırken bu fark belirginleşir.
import { shallowRef } from 'vue'
const bigData = shallowRef(loadHugeDataset())
// bigData.value'nun içindeki değişiklikler tetiklenmez,
// sadece referans değiştiğinde güncelleme olur
computed ile Türetilmiş Veriyi Önbelleğe Alın
Metotlar her render'da yeniden çalışırken, computed yalnızca bağımlılıkları değiştiğinde yeniden hesaplanır. Şablon içinde fonksiyon çağırmak yerine computed tercih edin.
// Kötü: her render'da çalışır
<p>{{ formatPrice(price) }}</p>
// İyi: sadece price değiştiğinde çalışır
const formattedPrice = computed(() => formatPrice(price.value))
2. Liste Render'larında key Kullanımı
v-for ile oluşturulan listelerde key vermek zorunlu gibi görünse de, çoğu geliştirici burada hata yapıyor. Index kullanmak, listenin sırası değiştiğinde Vue'nun yanlış elemanları yeniden kullanmasına neden olur.
<!-- Yanlış: index key -->
<li v-for="(item, index) in items" :key="index">
<!-- Doğru: benzersiz ve stabil bir id -->
<li v-for="item in items" :key="item.id">
Bunun ötesinde, çok büyük listelerle çalışıyorsanız sanal kaydırma (virtual scrolling) çözümlerine yönelin. vue-virtual-scroller veya vueuse içindeki useVirtualList gibi araçlar, binlerce satırı sorunsuz render etmenizi sağlar.
3. Bileşen Seviyesinde Optimizasyon
v-if ve v-show Arasındaki Seçim
v-if: Elemanı DOM'dan tamamen kaldırır. Nadiren görünen içerikler için idealdir.v-show: Sadecedisplay: noneuygular. Sık sık açılıp kapanan elemanlar için daha performanslıdır.
Yanlış tercih, gereksiz DOM manipülasyonuna veya gereksiz render maliyetine yol açar.
Bileşenleri Bölmek ve defineAsyncComponent Kullanmak
Büyük bileşenleri parçalara ayırmak, hem okunabilirliği hem de render performansını artırır. İlk ekranda görünmeyen bileşenleri ise asenkron olarak yükleyin.
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() =>
import('./components/HeavyChart.vue')
)
Bu yaklaşım, özellikle grafik kütüphaneleri, harita bileşenleri veya zengin metin editörleri gibi ağır bağımlılıklar için hayat kurtarıcıdır.
KeepAlive ile Bileşen Durumunu Koruyun
Sekmeler arası geçiş yapan uygulamalarda, her sekmeye dönüşte bileşeni yeniden oluşturmak yerine KeepAlive ile önbelleğe alın.
<KeepAlive :max="5">
<component :is="currentTab" />
</KeepAlive>
max parametresi, önbellekte tutulacak maksimum bileşen sayısını belirler ve bellek şişmesini önler.
4. Bundle Boyutunu Küçültmek
Yükleme performansı, kullanıcı deneyiminin ilk ve en kritik adımı.
Tree-Shaking'den Faydalanın
Vue 3, modüler yapısı sayesinde yalnızca kullandığınız API'leri bundle'a dahil eder. Ancak bunun için doğru import yöntemini kullanmanız gerekir.
// Doğru: tree-shake edilebilir
import { ref, computed } from 'vue'
// Yanlış: tüm Vue'yu çeker
import Vue from 'vue'
Route Bazlı Kod Bölme (Code Splitting)
Vue Router ile her route'u ayrı bir chunk olarak yükleyin. Kullanıcı yalnızca ziyaret ettiği sayfanın kodunu indirsin.
const routes = [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue')
}
]
Gereksiz Bağımlılıkları Denetleyin
npm ls --depth=0 komutuyla doğrudan bağımlılıklarınızı gözden geçirin. Kullanılmayan paketleri kaldırmak, hem bundle boyutunu hem de güvenlik yüzeyini küçültür. Bundle analizi için rollup-plugin-visualizer veya webpack-bundle-analyzer kullanabilirsiniz.
5. Render Fonksiyonları ve v-memo
Vue 3.2 ile gelen v-memo, belirli bir bağımlılık dizisi değişmediği sürece alt ağacın yeniden render edilmesini engeller. Özellikle büyük listelerde altın değerinde bir direktiftir.
<div v-memo="[item.id, item.selected]">
<!-- Sadece id veya selected değiştiğinde güncellenir -->
</div>
Bunun yanında, çok karmaşık render mantığı için render fonksiyonları veya JSX kullanmak, şablon derleyicisinin ürettiği ara kodlardan daha verimli olabilir. Ancak bu, okunabilirlikten ödün vermeniz anlamına gelir; bu nedenle yalnızca gerçekten darboğaz olan yerlerde tercih edin.
6. Olay Dinleyicileri ve Bellek Yönetimi
once ve passive Seçenekleri
Sadece bir kez tetiklenmesi gereken olay dinleyicileri için once kullanın. Scroll ve touch gibi sık tetiklenen olaylarda ise passive ile tarayıcıya performans ipucu verin.
<template>
<div @scroll.passive="onScroll" @click.once="trackClick" />
</template>
Zamanlayıcıları ve Abonelikleri Temizleyin
setInterval, setTimeout, addEventListener veya WebSocket abonelikleri gibi kaynakları onUnmounted (Vue 3) veya beforeDestroy (Vue 2) içinde mutlaka temizleyin. Aksi halde bileşen yok edilse bile arka planda çalışmaya devam ederler.
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
})
7. watch ve watchEffect Kullanımında Dikkat Edilmesi Gerekenler
watch ve watchEffect, reaktiviteyi izlemek için güçlü araçlar; ancak yanlış kullanıldıklarında gereksiz hesaplamalara yol açarlar.
deep: truekullanımından kaçının: Derin izleme, büyük nesnelerde ciddi performans maliyeti getirir. Bunun yerine belirli bir alanı izleyin.flush: 'post'tercih edin: DOM güncellemelerinden sonra çalışması gereken watcher'larda bu seçenek, gereksiz tetiklemeleri önler.watchEffectyerinewatchkullanın: Bağımlılıkları açıkça belirtmek, hangi değişikliğin neyi tetiklediğini netleştirir ve yan etkileri azaltır.
8. Üretim (Production) Modu ve Build Ayarları
Vue, development modunda çok daha fazla uyarı ve kontrol yapar. Üretim derlemesinde bu kontroller devre dışı kalır ve ciddi boyut kazancı sağlanır. Vite veya Vue CLI kullanıyorsanız, NODE_ENV=production ile derleme yaptığınızdan emin olun.
Ek olarak:
- Gzip/Brotli sıkıştırma etkinleştirin
- CDN üzerinden statik varlıkları sunun
- HTTP/2 veya HTTP/3 kullanın
- Cache-Control başlıklarını doğru yapılandırın
Bu adımlar Vue'ya özel olmasa da, framework seviyesindeki optimizasyonların etkisini katlar.
9. Ölçüm Yapmadan Optimize Etmeyin
En sık yapılan hata, "şu kısım yavaş olabilir" varsayımıyla optimizasyona girişmek. Önce ölçün, sonra müdahale edin.
- Vue DevTools Performance sekmesi: Bileşen render sürelerini ve tetiklenme sayılarını gösterir.
- Chrome DevTools Performance profili: Gerçek kullanıcı senaryolarında darboğazları ortaya çıkarır.
- Lighthouse ve Web Vitals: LCP, FID, CLS gibi metriklerle kullanıcı deneyimini sayısallaştırır.
performance.markveperformance.measure: Kritik kod yollarını manuel olarak ölçmek için kullanışlıdır.
Ölçüm sonuçları, hangi optimizasyonun gerçekten fark yaratacağını size söyler.
10. Yaygın Anti-Pattern'ler
Aşağıdaki kalıplar, performans sorunlarının büyük çoğunluğunu oluşturur:
- Şablon içinde fonksiyon çağırmak (her render'da yeniden çalışır)
v-foriçindev-ifkullanmak (önce filtreleyin, sonra döngü kurun)- Büyük nesneleri
dataveyareactiveiçine koymak - Global event listener'ları temizlememek
- Gereksiz yere
deep: trueile izleme yapmak - Aynı veriyi birden fazla
computediçinde yeniden hesaplamak - Route bazlı kod bölmeyi ihmal etmek
Bu listedeki her madde, gerçek projelerde sıkça karşılaşılan ve ölçülebilir kazanç sağlayan düzeltmelerdir.
Sonuç
Vue.js optimizasyonu, tek seferlik bir iş değil; geliştirme sürecinin her aşamasında uygulanması gereken bir disiplin. Reaktiviteyi bilinçli kullanmak, bundle'ı küçük tutmak, render maliyetlerini ölçmek ve bellek yönetimini ihmal etmemek; uzun vadede uygulamanızın hem hızını hem de sürdürülebilirliğini artırır.
Unutmayın: en iyi optimizasyon, ihtiyaç duyulmayan kodu hiç yazmamaktır. İkinci en iyi optimizasyon ise ölçerek, hedefe yönelik müdahale etmektir. Bu rehberdeki adımları kendi projenizin ihtiyaçlarına göre önceliklendirin; küçük ama tutarlı iyileştirmeler, zamanla büyük farklar yaratır.