Nuxt.js ile Modern Web Uygulamaları Geliştirme

Yunus Emre Güzel
13 Ocak 202515 dkFrontend
Nuxt.js ile Modern Web Uygulamaları Geliştirme

Nuxt.js ile Modern Web Uygulamaları Geliştirme

Nuxt.js, Vue.js ekosisteminin en güçlü meta-framework'ü olarak modern web uygulamaları geliştirmek için kapsamlı bir çözüm sunar. Bu yazıda, Nuxt 3'ün temel özelliklerini, performans optimizasyonlarını ve best practice'lerini detaylı olarak inceleyeceğiz.

Nuxt 3'ün Temel Özellikleri

Auto Imports ve Modüler Yapı

Nuxt 3'ün en dikkat çekici özelliklerinden biri, otomatik import sistemidir. Bu sistem, kod tekrarını azaltır ve geliştirme deneyimini iyileştirir.

// composables/useCounter.ts
export const useCounter = () => {
  const count = useState('count', () => 0)
  
  function increment() {
    count.value++
  }
  
  function decrement() {
    count.value--
  }
  
  return {
    count,
    increment,
    decrement
  }
}

// components/Counter.vue
<script setup>
// Auto-import sayesinde import ifadesi yazmaya gerek yok
const { count, increment, decrement } = useCounter()
</script>

<template>
  <div class="counter">
    <button @click="decrement">-</button>
    <span>{{ count }}</span>
    <button @click="increment">+</button>
  </div>
</template>

Nitro Engine ve Server Engine

Nuxt 3'ün güçlü sunucu motoru Nitro, universal deployment ve API geliştirme imkanı sunar.

// server/api/products.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event)
  const { page = 1, limit = 10 } = query
  
  try {
    const products = await prisma.product.findMany({
      skip: (Number(page) - 1) * Number(limit),
      take: Number(limit),
      orderBy: {
        createdAt: 'desc'
      }
    })
    
    const total = await prisma.product.count()
    
    return {
      products,
      pagination: {
        total,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(total / Number(limit))
      }
    }
  } catch (error) {
    throw createError({
      statusCode: 500,
      message: 'Ürünler yüklenirken bir hata oluştu'
    })
  }
})

// server/middleware/auth.ts
export default defineEventHandler((event) => {
  const token = getCookie(event, 'auth-token')
  
  if (!token && !event.path.startsWith('/api/public')) {
    throw createError({
      statusCode: 401,
      message: 'Unauthorized'
    })
  }
})

Composition API ve State Management

Nuxt 3, Vue 3'ün Composition API'sini tam olarak destekler ve güçlü state management çözümleri sunar.

// composables/useAuth.ts
export const useAuth = () => {
  const user = useState<User | null>('user', () => null)
  const loading = useState<boolean>('auth-loading', () => false)
  const error = useState<string | null>('auth-error', () => null)

  async function login(email: string, password: string) {
    loading.value = true
    error.value = null
    
    try {
      const response = await $fetch('/api/auth/login', {
        method: 'POST',
        body: { email, password }
      })
      
      user.value = response.user
      navigateTo('/dashboard')
    } catch (err) {
      error.value = 'Giriş başarısız'
    } finally {
      loading.value = false
    }
  }

  async function logout() {
    await $fetch('/api/auth/logout', { method: 'POST' })
    user.value = null
    navigateTo('/login')
  }

  return {
    user,
    loading,
    error,
    login,
    logout
  }
}

// pages/login.vue
<script setup>
const { login, loading, error } = useAuth()
const email = ref('')
const password = ref('')

async function handleSubmit() {
  await login(email.value, password.value)
}
</script>

<template>
  <form @submit.prevent="handleSubmit" class="login-form">
    <div v-if="error" class="error">{{ error }}</div>
    
    <input
      v-model="email"
      type="email"
      placeholder="E-posta"
      required
    />
    
    <input
      v-model="password"
      type="password"
      placeholder="Şifre"
      required
    />
    
    <button type="submit" :disabled="loading">
      {{ loading ? 'Giriş yapılıyor...' : 'Giriş Yap' }}
    </button>
  </form>
</template>

Routing ve Navigation

Nuxt 3'ün dosya sistemi tabanlı routing'i, karmaşık navigasyon yapılarını kolayca yönetmenizi sağlar.

// pages/index.vue
<script setup>
const route = useRoute()
const router = useRouter()

// Programmatik navigasyon
function goToProduct(id: string) {
  router.push(`/products/${id}`)
}
</script>

// pages/products/[id].vue
<script setup>
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

// Middleware kullanımı
definePageMeta({
  middleware: ['auth'],
  layout: 'product'
})
</script>

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const { user } = useAuth()
  
  if (!user.value && to.path !== '/login') {
    return navigateTo('/login')
  }
})

Performans Optimizasyonu

Image Optimization

Nuxt Image modülü ile otomatik görsel optimizasyonu:

<!-- components/OptimizedImage.vue -->
<script setup>
const props = defineProps({
  src: String,
  alt: String,
  width: {
    type: Number,
    default: 800
  }
})
</script>

<template>
  <nuxt-img
    :src="src"
    :alt="alt"
    :width="width"
    loading="lazy"
    format="webp"
    quality="80"
    placeholder
  />
</template>

<!-- nuxt.config.ts -->
export default defineNuxtConfig({
  image: {
    provider: 'cloudinary',
    cloudinary: {
      baseURL: 'https://res.cloudinary.com/your-account'
    },
    presets: {
      thumbnail: {
        modifiers: {
          width: 200,
          height: 200,
          fit: 'cover'
        }
      }
    }
  }
})

Code Splitting ve Lazy Loading

// Lazy loading components
const LazyComponent = defineAsyncComponent(() =>
  import('~/components/HeavyComponent.vue')
)

// Route level code splitting
export default defineNuxtConfig({
  experimental: {
    payloadExtraction: true,
    treeshakeClientOnly: true
  },
  nitro: {
    prerender: {
      routes: ['/'],
      crawlLinks: true
    }
  }
})

SEO ve Meta Tags

<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute()
const { data: article } = await useFetch(`/api/articles/${route.params.slug}`)

// SEO optimizasyonu
useHead({
  title: article.title,
  meta: [
    {
      name: 'description',
      content: article.description
    },
    {
      property: 'og:title',
      content: article.title
    },
    {
      property: 'og:description',
      content: article.description
    },
    {
      property: 'og:image',
      content: article.image
    }
  ],
  link: [
    {
      rel: 'canonical',
      href: `https://example.com/blog/${route.params.slug}`
    }
  ]
})
</script>

Error Handling ve Loading States

Error Boundaries

<!-- error.vue -->
<script setup>
const error = useError()

function handleError() {
  clearError({ redirect: '/' })
}
</script>

<template>
  <div class="error-page">
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.message }}</p>
    <button @click="handleError">
      Ana Sayfaya Dön
    </button>
  </div>
</template>

<!-- components/AsyncData.vue -->
<script setup>
const { data, pending, error, refresh } = await useFetch('/api/data')
</script>

<template>
  <div>
    <template v-if="pending">
      <LoadingSpinner />
    </template>
    
    <template v-else-if="error">
      <ErrorMessage
        :message="error.message"
        @retry="refresh"
      />
    </template>
    
    <template v-else>
      <DataDisplay :data="data" />
    </template>
  </div>
</template>

Deployment ve Build Optimizasyonu

Production Build

// nuxt.config.ts
export default defineNuxtConfig({
  // Build optimizasyonları
  build: {
    transpile: ['vue-toastification'],
    extractCSS: true,
    optimization: {
      splitChunks: {
        cacheGroups: {
          styles: {
            name: 'styles',
            test: /\.(css|vue)$/,
            chunks: 'all',
            enforce: true
          }
        }
      }
    }
  },
  
  // Nitro konfigürasyonu
  nitro: {
    preset: 'vercel',
    minify: true,
    compressPublicAssets: true,
    
    storage: {
      redis: {
        driver: 'redis',
        /* redis config */
      }
    }
  },
  
  // Modüller
  modules: [
    '@nuxtjs/robots',
    '@nuxt/image',
    '@nuxtjs/sitemap',
    '@nuxtjs/pwa'
  ],
  
  // PWA konfigürasyonu
  pwa: {
    manifest: {
      name: 'My Nuxt App',
      short_name: 'NuxtApp',
      theme_color: '#42b883'
    },
    workbox: {
      enabled: true
    }
  }
})

Best Practices ve İpuçları

  1. Composables Organizasyonu:

    • Mantıksal gruplandırma
    • Tek sorumluluk prensibi
    • TypeScript ile tip güvenliği
  2. State Management:

    • Composables ile modüler state
    • Pinia ile global state
    • SSR uyumlu state yönetimi
  3. Performance:

    • Lazy loading
    • Code splitting
    • Cache stratejileri
    • Image optimization
  4. Security:

    • Input validation
    • XSS koruması
    • CSRF token'ları
    • Rate limiting
  5. Testing:

    • Unit tests
    • Component tests
    • E2E tests
    • API tests

Sonuç

Nuxt 3, modern web uygulamaları geliştirmek için güçlü ve esnek bir framework sunar. Auto-imports, Nitro engine, ve gelişmiş performans özellikleri ile geliştirici deneyimini önemli ölçüde iyileştirir.

Framework'ün sunduğu özellikler:

  • Otomatik kod organizasyonu
  • Güçlü SSR desteği
  • Modüler yapı
  • Performans optimizasyonları
  • TypeScript desteği
  • Full-stack geliştirme imkanı

Bu özellikleri etkin kullanarak, hızlı, ölçeklenebilir ve bakımı kolay web uygulamaları geliştirebilirsiniz.

İlgili Etiketler: #Nuxtjs #Vuejs #Frontend #Performance #SSR #TypeScript #WebDevelopment #FullStack

Kaynaklar