Vue 3'te Performans ve Render Optimizasyonu Teknikleri

Yunus Emre Güzel
3 Ocak 202515 dkVue.js
Vue 3'te Performans ve Render Optimizasyonu Teknikleri

Vue 3'te Performans ve Render Optimizasyonu Teknikleri

Vue 3 uygulamalarında performans, kullanıcı deneyimini doğrudan etkileyen kritik bir faktördür. Bu yazıda, Vue 3'ün sunduğu performans optimizasyon tekniklerini, render optimizasyonlarını ve büyük veri setleriyle çalışırken kullanabileceğimiz stratejileri inceleyeceğiz.

Virtual DOM ve Render Optimizasyonu

Vue 3'ün yeni render motoru, Virtual DOM implementasyonunda önemli iyileştirmeler getirdi. İşte bu optimizasyonları maksimum verimle kullanmanın yolları:

Template Compilation Optimizasyonları

<template>
  <!-- Kötü Kullanım -->
  <div v-if="show">
    <ExpensiveComponent v-for="item in list" :key="item.id" />
  </div>

  <!-- İyi Kullanım -->
  <template v-if="show">
    <ExpensiveComponent v-for="item in list" :key="item.id" />
  </template>
</template>

<script setup>
import { defineComponent } from 'vue'

// Gereksiz wrapper div'den kaçınmak için Fragment kullanımı
defineComponent({
  name: 'OptimizedList'
})
</script>

Computed Properties ve Memorization

import { computed, ref } from 'vue'

const list = ref([/* büyük veri listesi */])
const searchQuery = ref('')

// Kötü Kullanım: Her render'da yeniden hesaplanır
const filteredList = () => {
  return list.value.filter(item => 
    item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
  )
}

// İyi Kullanım: Sadece bağımlılıklar değiştiğinde hesaplanır
const optimizedFilteredList = computed(() => {
  return list.value.filter(item => 
    item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
  )
})

// Çok parametreli hesaplamalar için custom memorization
function useMemoize(fn: Function) {
  const cache = new Map()
  
  return (...args: any[]) => {
    const key = JSON.stringify(args)
    if (cache.has(key)) return cache.get(key)
    
    const result = fn(...args)
    cache.set(key, result)
    return result
  }
}

Büyük Listelerin Optimizasyonu

Büyük veri setleriyle çalışırken performansı korumak için virtual scrolling ve chunk rendering teknikleri:

Virtual Scrolling Implementation

<template>
  <div class="virtual-list" :style="containerStyle">
    <div class="virtual-list-inner" :style="innerStyle">
      <template v-for="item in visibleItems" :key="item.id">
        <div class="list-item" :style="{ height: itemHeight + 'px' }">
          {{ item.content }}
        </div>
      </template>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onMounted, onUnmounted } from 'vue'

const props = defineProps<{
  items: Array<{ id: number; content: string }>
  itemHeight: number
}>()

const scrollTop = ref(0)
const containerHeight = ref(0)
const containerRef = ref<HTMLElement | null>(null)

// Görünür öğeleri hesapla
const visibleItems = computed(() => {
  const start = Math.floor(scrollTop.value / props.itemHeight)
  const count = Math.ceil(containerHeight.value / props.itemHeight)
  return props.items.slice(start, start + count + 1)
})

const containerStyle = computed(() => ({
  height: `${containerHeight.value}px`,
  overflow: 'auto',
  position: 'relative'
}))

const innerStyle = computed(() => ({
  height: `${props.items.length * props.itemHeight}px`,
  transform: `translateY(${Math.floor(scrollTop.value / props.itemHeight) * props.itemHeight}px)`
}))

const handleScroll = () => {
  if (containerRef.value) {
    scrollTop.value = containerRef.value.scrollTop
  }
}

onMounted(() => {
  if (containerRef.value) {
    containerHeight.value = containerRef.value.clientHeight
    containerRef.value.addEventListener('scroll', handleScroll)
  }
})

onUnmounted(() => {
  if (containerRef.value) {
    containerRef.value.removeEventListener('scroll', handleScroll)
  }
})
</script>

<style scoped>
.virtual-list {
  position: relative;
  overflow: auto;
}

.virtual-list-inner {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.list-item {
  padding: 8px;
  border-bottom: 1px solid #eee;
}
</style>

Chunk Rendering

Büyük listeleri parçalar halinde render etme:

import { ref, onMounted } from 'vue'

export function useChunkRendering<T>(items: T[], chunkSize = 100) {
  const renderedItems = ref<T[]>([])
  const currentChunk = ref(0)

  const renderNextChunk = () => {
    const start = currentChunk.value * chunkSize
    const chunk = items.slice(start, start + chunkSize)
    renderedItems.value = [...renderedItems.value, ...chunk]
    currentChunk.value++
  }

  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      renderNextChunk()
    }
  })

  onMounted(() => {
    renderNextChunk() // İlk chunk'ı render et
  })

  return {
    renderedItems,
    renderNextChunk
  }
}

// Kullanımı
const items = ref([/* büyük veri listesi */])
const { renderedItems, renderNextChunk } = useChunkRendering(items.value)

Component Render Optimizasyonu

defineAsyncComponent ile Lazy Loading

import { defineAsyncComponent } from 'vue'

// Ağır componenti lazy load et
const HeavyComponent = defineAsyncComponent(() =>
  import('./components/HeavyComponent.vue')
)

// Yükleme durumu ve hata yönetimi ile
const HeavyComponentWithOptions = defineAsyncComponent({
  loader: () => import('./components/HeavyComponent.vue'),
  loadingComponent: LoadingSpinner,
  errorComponent: ErrorComponent,
  delay: 200,
  timeout: 3000
})

shallowRef ve shallowReactive Kullanımı

Derin reaktivite gerektirmeyen durumlarda performans optimizasyonu:

import { shallowRef, shallowReactive } from 'vue'

// Sadece üst seviye değişiklikleri izle
const state = shallowReactive({
  user: {
    profile: {
      name: 'John',
      settings: { /* derin nested veriler */ }
    }
  }
})

// Büyük veri yapıları için shallow referans
const bigData = shallowRef({
  // Çok büyük nested veri yapısı
})

// Sadece referans değiştiğinde yeniden render
bigData.value = newBigData

Event Handling Optimizasyonu

Event Debouncing ve Throttling

import { ref } from 'vue'

export function useDebounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number
) {
  let timeout: NodeJS.Timeout

  return (...args: Parameters<T>) => {
    clearTimeout(timeout)
    timeout = setTimeout(() => fn(...args), delay)
  }
}

// Kullanımı
const searchQuery = ref('')
const debouncedSearch = useDebounce((query: string) => {
  // API çağrısı yap
  fetchSearchResults(query)
}, 300)

// Template'de
// <input v-model="searchQuery" @input="debouncedSearch(searchQuery)" />

Memory Leak Önleme

Composition API ile Cleanup

import { onUnmounted, onMounted } from 'vue'

export function useEventListener(
  target: Window | HTMLElement,
  event: string,
  callback: EventListener
) {
  onMounted(() => target.addEventListener(event, callback))
  
  // Cleanup
  onUnmounted(() => target.removeEventListener(event, callback))
}

// WebSocket bağlantıları için cleanup örneği
export function useWebSocket(url: string) {
  const ws = new WebSocket(url)
  
  onUnmounted(() => {
    ws.close()
  })
  
  return ws
}

Performance Monitoring

Custom Performance Metrics

import { onMounted, onUpdated } from 'vue'

export function usePerformanceMonitoring(componentName: string) {
  let startTime: number

  onMounted(() => {
    startTime = performance.now()
    
    // Component mount süresini ölç
    requestAnimationFrame(() => {
      const mountTime = performance.now() - startTime
      console.log(`${componentName} mount time:`, mountTime)
    })
  })

  onUpdated(() => {
    const updateTime = performance.now() - startTime
    console.log(`${componentName} update time:`, updateTime)
  })
}

Sonuç

Vue 3'te performans optimizasyonu, birçok farklı teknik ve yaklaşımın bir kombinasyonudur. Virtual DOM optimizasyonları, computed properties'in doğru kullanımı, büyük listelerin verimli yönetimi ve component lazy loading gibi tekniklerin uygun şekilde kullanılması, uygulamanızın performansını önemli ölçüde artırabilir.

Bu optimizasyon tekniklerini uygularken, her zaman önce performans ölçümü yapmanız ve gerçekten bir optimizasyona ihtiyaç olup olmadığını belirlemeniz önemlidir. Erken optimizasyon, kod karmaşıklığını artırabilir ve bakım maliyetlerini yükseltebilir.

İlgili Etiketler: #Vuejs #Performance #Optimization #VirtualDOM #CompositionAPI #Frontend #JavaScript #WebDevelopment

Kaynaklar