Vue.js uygulamalarında performans genellikle iki katmanda belirlenir: derleyicinin ürettiği kod ve çalışma zamanındaki reaktivite davranışı. Bu rehber, orta seviye geliştiriciler için bu iki katmana odaklanır; ölçüm almayı, reaktiviteyi doğru kurmayı, render maliyetini düşürmeyi ve büyük listelerle kod bölmeyi sıralı biçimde ele alır.
Önkoşullar ve kapsam
- Vue 3 ve Composition API (
<script setup>) bilgisi. - Bileşen yaşam döngüsü,
props/emitvev-modelkullanımına aşinalık. - Örnekler Vue 3 sözdizimini kullanır. Vue 2'de reaktivite sistemi farklıdır (
Object.defineProperty), bu yüzden buradaki bazı teknikler doğrudan taşınmaz.
Sürüm numarası vermekten kaçınıyorum; aşağıdaki API'ler Vue 3'ün kararlı yüzeyidir. Kullandığınız sürümün davranışını kendi projenizde doğrulayın.
1. Önce ölçün, sonra değiştirin
Optimizasyonun en yaygın hatası, darboğazı bilmeden kod değiştirmektir. İki araç yeterlidir:
- Tarayıcı Performance paneli: Uzun görevleri (long task), bileşen render sürelerini ve layout thrashing'i gösterir.
- Vue DevTools (Performance sekmesi): Bileşen bazında render süresi ve render sayısını ölçer.
Ölçüm yapmadan v-if/v-show değiştirmek veya memo benzeri çözümlere sarılmak, çoğu zaman karmaşıklığı artırıp kazancı belirsiz bırakır.
2. Reaktiviteyi bilinçli kurun
ref ve reactive arasında doğru seçim
reactive yalnızca nesnelerde çalışır ve nesnenin kendisini yeniden atayamazsınız. ref ise her değer tipini sarar ve .value üzerinden erişilir. Şablon içinde ref otomatik açılır; script içinde açılmaz.
<script setup>
import { ref, reactive } from 'vue'
const count = ref(0) // primitive için uygun
const user = reactive({ name: 'Ada', age: 36 }) // grup halinde tutulan nesne için uygun
function increment() {
count.value++ // script içinde .value zorunlu
}
</script>
Beklenen davranış: count değiştiğinde yalnızca onu okuyan render efektleri yeniden çalışır. user.age değiştiğinde user üzerinden okunan efektler tetiklenir.
Türetilmiş değerler için computed
Bir değer başka reaktif değerlerden hesaplanıyorsa, onu ref içinde elle güncellemek yerine computed kullanın. computed sonucu önbelleğe alır ve bağımlılıkları değişmedikçe yeniden hesaplanmaz.
import { ref, computed } from 'vue'
const items = ref([/* ... */])
const total = computed(() => items.value.reduce((sum, i) => sum + i.price, 0))
total, items değişene kadar tekrar hesaplanmaz. Bunu bir watch içinde elle güncellerseniz, hem gereksiz render hem de senkronizasyon hatası riski doğar.
watch ve watchEffect maliyeti
watch bir yan etki (ağ isteği, DOM işlemi, üçüncü parti kütüphane çağrısı) için uygundur; render için değil. Sık değişen bir kaynağı izliyorsanız ve yan etkiyi seyrekleştirmek istiyorsanız flush ve zamanlama seçeneklerini değerlendirin:
import { watch } from 'vue'
watch(query, (value) => {
// her tuş vuruşunda değil, uygun bir gecikmeyle çalışsın
}, { flush: 'post' })
flush: 'post' yan etkinin DOM güncellendikten sonra çalışmasını sağlar. flush: 'sync' ise her değişimde anında çalışır ve genellikle performans açısından istenmeyen bir tercihtir.
3. Render maliyetini düşürün
v-if ve v-show
v-ifDOM'dan tamamen çıkarır; ilk render maliyeti düşük, geçiş maliyeti yüksektir.v-showyalnızcadisplaydeğiştirir; sık açılıp kapanan ama nadiren değişen içerik için uygundur.
Sekme gibi sık değişen ama içeriği pahalı olan yapılarda v-show yerine v-if ile bileşeni tamamen kaldırmak, arka planda çalışan efektleri de durdurur.
v-for üzerinde :key
key olarak dizi indeksi kullanmak, liste sırası değiştiğinde Vue'nun yanlış düğümleri yeniden kullanmasına ve gereksiz DOM işlemine yol açar. Kararlı ve benzersiz bir kimlik kullanın:
<li v-for="item in items" :key="item.id">{{ item.title }}</li>
Pahalı hesaplamaları şablondan çıkarın
Şablon içindeki metot çağrıları her render'da yeniden çalışır. Filtreleme, sıralama veya biçimlendirme gibi işleri computed içine taşıyın:
<!-- Kaçının: her render'da yeniden hesaplanır -->
<li v-for="item in items.filter(i => i.active)" :key="item.id">
<!-- Tercih edin -->
<li v-for="item in activeItems" :key="item.id">
4. Bileşen sınırlarını doğru çizin
Bir üst bileşenin state'i değiştiğinde, alt bileşenlerin props'u değişmese bile render tetiklenebilir. Bunu azaltmanın pratik yolları:
- State'i mümkün olduğunca aşağı taşıyın. Yalnızca bir alt bileşenin ihtiyaç duyduğu state'i üstte tutmak, tüm ağacı gereksiz yere render ettirir.
- Slot kullanımını bilinçli yapın. Slot içeriği üst bileşenin render'ına bağlıdır; derin ve pahalı slot içerikleri üstteki her güncellemede yeniden render edilebilir.
v-oncevev-memo'yu ölçerek kullanın.v-oncebir alt ağacı yalnızca bir kez render eder; statik içerik için uygundur.v-memoise belirtilen bağımlılıklar değişmedikçe alt ağacı atlar:
<div v-memo="[item.id, item.selected]">
<!-- yalnızca id veya selected değiştiğinde yeniden render edilir -->
</div>
Bu direktifler yanlış kullanıldığında beklenmeyen güncellenmeme hatalarına yol açar; yalnızca ölçüm sonrası ve dar kapsamda uygulayın.
5. Büyük listeler ve kod bölme
Sanallaştırma
Yüzlerce satırı aynı anda DOM'a basmak, render ve bellek maliyetini doğrusal olarak artırır. Görünür alanı ve yakın çevresini render eden bir sanallaştırma çözümü (örneğin vue-virtual-scroller gibi topluluk kütüphaneleri) bu maliyeti sabitler. Kütüphane seçerken bakım durumunu ve Vue 3 uyumluluğunu kontrol edin.
Rota ve bileşen seviyesinde kod bölme
Başlangıç paketini küçültmek için ağır rotaları ve nadiren kullanılan bileşenleri tembel yükleyin:
// Router yapılandırmasında
const routes = [
{ path: '/raporlar', component: () => import('./views/Reports.vue') }
]
<script setup>
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() => import('./HeavyChart.vue'))
</script>
Beklenen davranış: ilgili bileşen yalnızca ihtiyaç duyulduğunda indirilir; ilk yükteki JavaScript miktarı azalır. Ağ gecikmesinin yüksek olduğu senaryolarda yükleme durumunu (Suspense veya defineAsyncComponent'in yükleme bileşeni) ele almayı unutmayın.
6. Yaygın hatalar
- Ölçmeden optimize etmek. En sık görülen hata budur; kazancı doğrulanamayan değişiklikler teknik borç bırakır.
v-foriçinde indekskeykullanmak. Liste yeniden sıralandığında yanlış düğümlerin yeniden kullanılmasına yol açar.- Türetilmiş veriyi
watchile elle senkronlamak.computed'ın yerini alması gereken yerde kullanıldığında gereksiz render ve tutarsız state üretir. - Şablonda ağır fonksiyon çağırmak. Her render'da yeniden çalışır;
computed'a taşınmalıdır. v-memo/v-once'u geniş kapsamda uygulamak. Güncellenmeyen arayüz hatalarıyla sonuçlanır.
7. Güvenlik etkileri
Performans çalışması sırasında gözden kaçabilen birkaç nokta:
v-htmlkullanımı. Performans için değil ama güvenlik için kritiktir: kullanıcı girdisini doğrudanv-htmlile basmak XSS'e açık kapı bırakır. Girdiyi güvenilir bir sanitizasyon adımından geçirmeden kullanmayın.- Tembel yüklenen modüller. Dinamik
importile yüklenen kod, uygulamanın geri kalanıyla aynı kaynak politikalarına tabidir. İçerik Güvenliği Politikası (CSP) yapılandırmanızın bu parçalarla uyumlu olduğundan emin olun. - Üçüncü parti sanallaştırma/bileşen kütüphaneleri. Bakımı sürdürülen, kaynağı bilinen paketleri tercih edin; bağımlılık zinciri uygulamanızın saldırı yüzeyini doğrudan etkiler.
Sonuç
Vue.js optimizasyonu tek bir ayarla çözülmez. Sıralı yaklaşım şudur: ölçün, reaktiviteyi doğru modelleyin, render maliyetini computed ve doğru key ile düşürün, bileşen sınırlarını bilinçli çizin, büyük listeleri ve başlangıç paketini kod bölmeyle hafifletin. Her adımı kendi projenizde ölçerek doğrulayın; ölçüm olmadan yapılan değişiklikler beklenen kazancı sağlamaz.