Nuxt Nitro i Server Routes w 2026: Full-Stack Vue i API Endpoints
Opanuj Nuxt Nitro server routes do budowania aplikacji full-stack Vue. Poznaj API endpoints, middleware, integrację z bazą danych oraz wzorce wdrożeń produkcyjnych z Nuxt 4.

Nuxt Nitro przekształca aplikacje Vue w pełnoprawne rozwiązania full-stack, dostarczając uniwersalny silnik serwerowy obsługujący API routes, middleware oraz logikę serwerową obok komponentów frontendowych. Wraz z Nuxt 4.3 i nadchodzącym Nitro v3, budowanie produkcyjnych backendów nigdy nie było tak zintegrowane z rozwojem Vue.
Nitro umożliwia współdzielenie typów TypeScript między frontendem a backendem, eliminując rozbieżności kontraktów API i redukując boilerplate. Server routes znajdują się w server/api/ i automatycznie stają się dostępne jako endpointy /api/*.
Architektura silnika Nuxt Nitro Server
Nitro służy jako uniwersalne środowisko uruchomieniowe JavaScript zasilające katalog server w Nuxt. W przeciwieństwie do tradycyjnych serwerów Node.js, Nitro kompiluje do bundli zoptymalizowanych pod konkretne platformy, które wdrażają się bezproblemowo na Vercel, Netlify, Cloudflare Workers oraz standardowe środowiska Node.js bez zmian w kodzie.
Architektura rozdziela odpowiedzialności poprzez konwencje katalogów:
export default defineEventHandler(async (event) => {
// Nitro auto-serializes return values to JSON
// HTTP method suffix (.get.ts) restricts to GET requests
const users = await getUsersFromDatabase()
return { users, count: users.length }
})Nitro skanuje cztery katalogi: server/api dla API routes z prefiksem /api, server/routes dla routes bez prefiksu, server/middleware dla interceptorów żądań oraz server/utils dla współdzielonych narzędzi serwerowych. Pliki poza tymi katalogami pozostają niewidoczne dla środowiska serwerowego.
Tworzenie RESTful API Endpoints z defineEventHandler
Server routes podążają za konwencjami routingu opartymi na plikach, gdzie nazwy plików mapują bezpośrednio na ścieżki URL. Sufiksy metod HTTP kontrolują, które żądania akceptuje każdy handler.
// Handles GET /api/products/123
export default defineEventHandler(async (event) => {
// Extract route parameter from URL
const id = getRouterParam(event, 'id')
if (!id) {
throw createError({
status: 400, // Nuxt 4 uses Web API naming (not statusCode)
statusText: 'Product ID required' // Not statusMessage
})
}
const product = await fetchProduct(id)
if (!product) {
throw createError({
status: 404,
statusText: 'Product not found'
})
}
return product
})Nuxt 4 przyjmuje konwencje nazewnictwa Web API w przygotowaniu do Nitro v3. Właściwość statusCode zmienia się na status, a statusMessage na statusText. Chociaż starsze właściwości nadal działają, migracja do nowego nazewnictwa zapewnia kompatybilność z Nuxt 5.
Obsługa żądań POST z walidacją body:
// Handles POST /api/products
import { z } from 'zod'
const ProductSchema = z.object({
name: z.string().min(1).max(200),
price: z.number().positive(),
category: z.enum(['electronics', 'clothing', 'food'])
})
export default defineEventHandler(async (event) => {
// readBody automatically parses JSON
const body = await readBody(event)
// Validate with Zod schema
const result = ProductSchema.safeParse(body)
if (!result.success) {
throw createError({
status: 422,
statusText: 'Validation failed',
data: result.error.flatten()
})
}
const product = await createProduct(result.data)
// Set 201 Created status for resource creation
setResponseStatus(event, 201)
return product
})Server Middleware dla uwierzytelniania i logowania
Pliki middleware wykonują się przed handlerami tras, umożliwiając obsługę przekrojowych zagadnień takich jak uwierzytelnianie, logowanie i transformacja żądań. W przeciwieństwie do handlerów tras, middleware nie zwraca bezpośrednio odpowiedzi.
export default defineEventHandler(async (event) => {
// Skip auth for public routes
const publicRoutes = ['/api/health', '/api/auth/login']
if (publicRoutes.includes(event.path)) {
return // Continue to next handler
}
const authHeader = getHeader(event, 'authorization')
if (!authHeader?.startsWith('Bearer ')) {
throw createError({
status: 401,
statusText: 'Authentication required'
})
}
const token = authHeader.slice(7)
try {
// Verify JWT and attach user to event context
const user = await verifyToken(token)
event.context.user = user
} catch {
throw createError({
status: 401,
statusText: 'Invalid or expired token'
})
}
})Obiekt event.context utrzymuje się między middleware a handlerami w ramach pojedynczego żądania, zapewniając typowo-bezpieczny sposób współdzielenia danych. Typy kontekstu definiuje się w pliku deklaracji:
declare module 'h3' {
interface H3EventContext {
user?: {
id: string
email: string
role: 'admin' | 'user'
}
}
}Do przygotowań do rozmów kwalifikacyjnych dotyczących koncepcji serwera Nuxt warto zapoznać się z modułem pytań rekrutacyjnych o Nuxt Server Routes.
Gotowy na rozmowy o Vue.js / Nuxt.js?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Integracja bazy danych z Prisma i Server Utils
Narzędzia serwerowe w server/utils/ automatycznie importują się w całym kodzie serwerowym, czyniąc klienty baz danych i współdzieloną logikę dostępnymi bez jawnych importów.
import { PrismaClient } from '@prisma/client'
// Singleton pattern prevents multiple instances in development
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient({
log: process.env.NODE_ENV === 'development'
? ['query', 'error', 'warn']
: ['error']
})
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}Z globalnie dostępnym klientem bazy danych, handlery tras uzyskują do niego bezpośredni dostęp:
export default defineEventHandler(async (event) => {
// Query parameters for pagination
const query = getQuery(event)
const page = Number(query.page) || 1
const limit = Math.min(Number(query.limit) || 10, 100)
const skip = (page - 1) * limit
// Parallel queries for data and count
const [posts, total] = await Promise.all([
prisma.post.findMany({
skip,
take: limit,
orderBy: { createdAt: 'desc' },
include: { author: { select: { name: true, avatar: true } } }
}),
prisma.post.count()
])
return {
posts,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
}
}
})Server Plugins dla inicjalizacji runtime
Pluginy serwerowe w server/plugins/ wykonują się raz podczas startu serwera, idealnie nadając się do inicjalizacji połączeń, planowania zadań lub konfiguracji monitoringu.
export default defineNitroPlugin(async (nitroApp) => {
// Verify database connection on startup
try {
await prisma.$connect()
console.log('Database connected successfully')
} catch (error) {
console.error('Database connection failed:', error)
process.exit(1) // Fail fast if DB unavailable
}
// Graceful shutdown hook
nitroApp.hooks.hook('close', async () => {
await prisma.$disconnect()
console.log('Database disconnected')
})
})System pluginów integruje się z hookami Nitro do zarządzania cyklem życia. Hooki uruchamiają się w określonych momentach: request przed obsługą, beforeResponse przed wysłaniem i close podczas zamykania.
Typowo-bezpieczne wywołania API z komponentów Vue
Narzędzie $fetch w Nuxt zapewnia wnioskowanie typów z tras serwerowych przy użyciu aliasu ~/server. W połączeniu z composable useFetch, komponenty konsumują API z pełnym wsparciem TypeScript.
<script setup lang="ts">
// Inferred return type from server/api/products/[id].get.ts
const route = useRoute()
const { data: product, status, error } = await useFetch(
`/api/products/${route.params.id}`
)
// Mutation with optimistic updates
const { execute: updateProduct, status: updateStatus } = useFetch(
`/api/products/${route.params.id}`,
{
method: 'PATCH',
immediate: false, // Don't fetch on mount
watch: false // Don't refetch on dependency change
}
)
async function handleUpdate(updates: Partial<Product>) {
await updateProduct({ body: updates })
// Refetch to sync state
await refreshNuxtData(`product-${route.params.id}`)
}
</script>
<template>
<div v-if="status === 'pending'">Loading...</div>
<div v-else-if="error">{{ error.message }}</div>
<ProductDetail v-else :product="product" @update="handleUpdate" />
</template>Strategie cachowania dla Server Routes
Nuxt 4.3 wprowadza ulepszone kontrole cachowania poprzez routeRules w nuxt.config.ts. Server routes korzystają z tej samej infrastruktury cachowania co strony.
export default defineNuxtConfig({
routeRules: {
// Cache product listings for 5 minutes
'/api/products': {
cache: {
maxAge: 300,
staleMaxAge: 600, // Serve stale while revalidating
swr: true
}
},
// No cache for user-specific data
'/api/user/**': { cache: false },
// Pre-render static API responses at build time
'/api/categories': { prerender: true }
}
})Dla dynamicznej inwalidacji cache należy użyć wrappera defineCachedEventHandler:
export default defineCachedEventHandler(async (event) => {
const trending = await calculateTrendingProducts()
return trending
}, {
maxAge: 60 * 5, // 5 minutes
name: 'trending-products',
getKey: () => 'trending', // Cache key for invalidation
shouldBypassCache: (event) => {
// Bypass for admin users
return event.context.user?.role === 'admin'
}
})Obsługa błędów i formatowanie odpowiedzi
Spójne odpowiedzi błędów poprawiają użyteczność API. Należy utworzyć współdzielone narzędzie do obsługi błędów:
import { H3Error } from 'h3'
export function handleDatabaseError(error: unknown): never {
console.error('Database error:', error)
// Prisma-specific error handling
if (error instanceof Error && 'code' in error) {
const prismaError = error as { code: string }
if (prismaError.code === 'P2002') {
throw createError({
status: 409,
statusText: 'Resource already exists'
})
}
if (prismaError.code === 'P2025') {
throw createError({
status: 404,
statusText: 'Resource not found'
})
}
}
throw createError({
status: 500,
statusText: 'Internal server error'
})
}Dla kompleksowych wzorców Vue.js i zarządzania stanem warto zapoznać się z artykułem porównanie Pinia vs Vuex.
Przed wdrożeniem serwerów Nitro należy: zwalidować zmienne środowiskowe schematami Zod, zaimplementować middleware rate limiting, dodać logowanie żądań do debugowania oraz skonfigurować nagłówki CORS dla cross-origin dostępu do API.
Wdrożenie na różnych platformach
System presetów Nitro generuje zoptymalizowane buildy dla każdej platformy:
export default defineNuxtConfig({
nitro: {
// Auto-detected on Vercel/Netlify, or specify manually
preset: 'node-server', // 'vercel', 'netlify', 'cloudflare-workers'
// Compress responses
compressPublicAssets: true,
// External packages not to bundle
externals: {
external: ['@prisma/client']
}
}
})Dla wdrożeń Node.js, output zawiera samodzielny serwer:
# Build for production
npm run build
# Start the server
node .output/server/index.mjsNuxt 3 osiąga koniec wsparcia 31 lipca 2026. Projekty powinny migrować do Nuxt 4 używając oficjalnego przewodnika migracji. Nuxt 5 z Nitro v3 pojawi się wkrótce potem.
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Podsumowanie
- Server routes w
server/api/automatycznie mapują się na endpointy/api/*z sufiksami metod HTTP (.get.ts,.post.ts) kontrolującymi typy żądań - Middleware w
server/middleware/obsługuje uwierzytelnianie, logowanie i transformację żądań przed wykonaniem tras - Obiekt
event.contextwspółdzieli typowane dane między middleware a handlerami w ramach żądania - Narzędzia serwerowe w
server/utils/automatycznie importują się w kodzie serwerowym, idealnie dla klientów baz danych i współdzielonej logiki - Nuxt 4 przyjmuje nazewnictwo Web API (
status/statusText) w przygotowaniu do Nitro v3 defineCachedEventHandlerzapewnia cachowanie na poziomie tras z kontrolami inwalidacji- Presety Nitro umożliwiają bezproblemowe wdrożenia na Vercel, Netlify, Cloudflare i serwery Node.js
Tagi
Udostępnij
Powiązane artykuły

Nuxt 4 w 2026: Nowa Struktura Katalogow i Migracja z Nuxt 3
Kompletny przewodnik po Nuxt 4: nowa struktura katalogu app/, migracja krok po kroku z Nuxt 3, singleton data fetching, shallow reactivity, TypeScript context splitting, Vue Router v5, zarzadzanie meta tagami i lista kontrolna migracji.

Zaawansowane Vue 3 Composables: Wzorce wielokrotnego uzytku i pytania rekrutacyjne 2026
Kompleksowy przewodnik po zaawansowanych Vue 3 Composables z wzorcami wielokrotnego uzytku, asynchroniczna obsluga bledow, Dependency Injection, walidacja formularzy i aktualne pytania rekrutacyjne na 2026 rok.

Testowanie Vue 3 w 2026: Vitest, Vue Test Utils i pytania rekrutacyjne
Praktyczny przewodnik po testowaniu Vue w 2026: konfiguracja Vitest, montowanie komponentów z Vue Test Utils, testowanie composables i stores Pinia, mockowanie API, pomiar pokrycia oraz pytania zadawane na rozmowach kwalifikacyjnych.