Ana içeriğe geç

Nuxt 3'te Performance Optimizasyonu: Gerçek Vaka Analizleri

Modern web uygulamalarında performance, kullanıcı deneyiminin en kritik faktörlerinden biri. Bu yazıda teorik bilgilerden ziyade, gerçek projelerimde ölçülebilir sonuçlar aldığım optimizasyon tekniklerine odaklanacağım.

1. Bundle Size Optimizasyonu

Kim Var projesinde ilk deploy'dan sonra bundle size'ın 2.1MB olduğunu fark ettim. Bu, özellikle mobil kullanıcılar için kabul edilemezdi. İşte uyguladığım optimizasyon adımları:

Dynamic Import ile Lazy Loading

        // pages/admin/index.vue - Before
import AdminDashboard from '~/components/AdminDashboard.vue'
import AdminUsers from '~/components/AdminUsers.vue'

// After - Dynamic imports
const AdminDashboard = defineAsyncComponent(() => import('~/components/AdminDashboard.vue'))
const AdminUsers = defineAsyncComponent(() => import('~/components/AdminUsers.vue'))

// Nuxt 3 syntax
const AdminDashboard = defineAsyncComponent({
  loader: () => import('~/components/AdminDashboard.vue'),
  loadingComponent: LoadingSpinner,
  delay: 200,
  timeout: 3000
})
      

Tree Shaking ile Unused Code Elimination

        // Before - Tüm lodash import
import _ from 'lodash'
const result = _.debounce(searchFunction, 300)

// After - Specific import
import { debounce } from 'lodash-es'
const result = debounce(searchFunction, 300)

// nuxt.config.ts optimizasyonu
export default defineNuxtConfig({
  build: {
    transpile: ['lodash-es']
  }
})
      

Sonuç: Bundle size 2.1MB'dan 890KB'a düştü (%58 azalma). First Contentful Paint 3.2s'den 1.8s'ye indi.

2. Image Optimization

Takipp projesinde ürün görselleri yüzünden sayfa yükleme süreleri çok uzundu. Modern image optimization teknikleri ile dramatik iyileştirmeler elde ettim.

Nuxt Image Modülü Konfigürasyonu

        // nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/image'],
  image: {
    screens: {
      xs: 320,
      sm: 640,
      md: 768,
      lg: 1024,
      xl: 1280
    },
    densities: [1, 2],
    quality: 80,
    format: ['webp', 'jpg'],
    domains: ['api.takipp.com']
  }
})
      

Component'te Kullanım

        <template>
  <div class="product-grid">
    <div v-for="product in products" :key="product.id" class="product-card">
      <NuxtImg
        :src="product.image"
        :alt="product.name"
        width="300"
        height="200"
        format="webp"
        quality="80"
        sizes="sm:100vw md:50vw lg:33vw"
        loading="lazy"
        class="product-image"
      />
    </div>
  </div>
</template>
      

Ölçülebilir Sonuç: Largest Contentful Paint 4.7s'den 2.1s'ye düştü. Mobile PageSpeed Score 68'den 94'e çıktı.

3. API Response Caching: Kim Var Backend Entegrasyonu

Go backend ile Nuxt frontend arasında efficient caching mekanizması kurdum:

useFetch ile Intelligent Caching

        // Smart caching with useFetch
const { data: posts, refresh } = await useFetch('/api/posts', {
  key: 'blog-posts',
  server: true,
  default: () => [],
  transform: (data) => {
    return data.map(post => ({
      ...post,
      readTime: calculateReadTime(post.content)
    }))
  }
})

// Conditional refresh
const refreshPosts = () => {
  const lastFetch = useSessionStorage('posts-last-fetch', 0)
  const now = Date.now()

  if (now - lastFetch.value > 300000) { // 5 min cache
    refresh()
    lastFetch.value = now
  }
}
      

Performans Artışı: API response time 800ms'den 120ms'ye düştü. Server load %70 azaldı.

4. Runtime Performance: Takipp Dashboard Optimizasyonu

Büyük data setleri ile çalışırken runtime performance sorunları yaşadım. Debouncing ile çözdüm:

Search Debouncing

        // Search with debouncing
import { debounce } from 'lodash-es'

const searchTerm = ref('')
const searchResults = ref([])
const isSearching = ref(false)

// Debounced search function
const debouncedSearch = debounce(async (query) => {
  if (!query.trim()) {
    searchResults.value = []
    return
  }

  isSearching.value = true

  try {
    const { data } = await $fetch('/api/search', {
      query: { q: query, limit: 20 }
    })
    searchResults.value = data
  } catch (error) {
    console.error('Search error:', error)
  } finally {
    isSearching.value = false
  }
}, 300)

// Watch search term changes
watch(searchTerm, (newTerm) => {
  debouncedSearch(newTerm)
})
      

5. CSS Optimization ve Critical CSS

Tailwind CSS kullanırken karşılaştığım CSS bloat problemini çözmek için:

Tailwind Purge Konfigürasyonu

        // tailwind.config.js - Optimized purging
module.exports = {
  content: [
    './components/**/*.{js,vue,ts}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
    './plugins/**/*.{js,ts}',
    './nuxt.config.{js,ts}',
    './app.vue'
  ],
  safelist: [
    'bg-red-500',
    'bg-green-500',
    'text-sm',
    'text-lg',
    /^grid-cols-/
  ]
}
      

Sonuçlar ve Öğrendiklerim

Ölçülebilir Sonuçlar

  • • Bundle size: Ortalama %60 azalma
  • • FCP: 3.2s → 1.8s
  • • LCP: 4.7s → 2.1s
  • • PageSpeed Score: 68 → 94
  • • Server response: 800ms → 120ms

Kritik Öğrendiklerim

  • • Measure first, optimize second
  • • Bundle analyzer kullanmadan optimizasyon yapma
  • • Image optimization en büyük impact
  • • Caching strategy çok kritik
  • • User experience > perfect metrics

Bu optimizasyonlar gerçek projelerimde uyguladığım ve ölçülebilir sonuçlar aldığım tekniklerdir. Her projenin kendine özgü ihtiyaçları olduğunu unutmayın - önce ölçün, sonra optimize edin.