Nuxt Nitro та Server Routes у 2026: Full-Stack Vue та API Endpoints
Опануйте Nuxt Nitro server routes для створення full-stack Vue застосунків. Дізнайтеся про API endpoints, middleware, інтеграцію з базою даних та патерни production deployment з Nuxt 4.

Nuxt Nitro перетворює Vue застосунки на повноцінні full-stack рішення, надаючи універсальний серверний движок, який обробляє API routes, middleware та серверну логіку поряд із фронтенд компонентами. З Nuxt 4.3 та майбутнім Nitro v3 створення production-ready бекендів ніколи не було настільки інтегрованим з Vue розробкою.
Nitro дозволяє спільно використовувати TypeScript типи між фронтендом та бекендом, усуваючи розбіжності API контрактів та зменшуючи boilerplate код. Server routes знаходяться в server/api/ і автоматично стають доступними як /api/* endpoints.
Архітектура серверного движка Nuxt Nitro
Nitro служить універсальним JavaScript серверним середовищем виконання, що забезпечує роботу директорії server в Nuxt. На відміну від традиційних Node.js серверів, Nitro компілює оптимізовані під платформу bundle'и, які безперешкодно розгортаються на Vercel, Netlify, Cloudflare Workers та стандартних Node.js середовищах без змін у коді.
Архітектура розділяє відповідальності через конвенції директорій:
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 сканує чотири директорії: server/api для API routes з префіксом /api, server/routes для routes без префікса, server/middleware для перехоплювачів запитів та server/utils для спільних серверних утиліт. Файли поза цими директоріями залишаються невидимими для серверного середовища.
Створення RESTful API Endpoints з defineEventHandler
Server routes дотримуються конвенцій файлового роутингу, де імена файлів безпосередньо відповідають URL шляхам. Суфікси HTTP методів контролюють, які запити приймає кожен 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 приймає конвенції іменування Web API в підготовці до Nitro v3. Властивість statusCode стає status, а statusMessage стає statusText. Хоча застарілі властивості досі працюють, міграція на нове іменування забезпечує сумісність з Nuxt 5.
Обробка POST запитів з валідацією 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 для автентифікації та логування
Файли middleware виконуються перед route handlers, дозволяючи обробляти наскрізні задачі такі як автентифікація, логування та трансформація запитів. На відміну від route handlers, middleware не повертає відповіді безпосередньо.
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'
})
}
})Об'єкт event.context зберігається між middleware та handlers в межах одного запиту, забезпечуючи типобезпечний спосіб обміну даними. Типи контексту визначаються у файлі декларацій:
declare module 'h3' {
interface H3EventContext {
user?: {
id: string
email: string
role: 'admin' | 'user'
}
}
}Для підготовки до співбесід щодо концепцій Nuxt server варто ознайомитися з модулем питань на співбесіду про Nuxt Server Routes.
Готовий до співбесід з Vue.js / Nuxt.js?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
Інтеграція бази даних з Prisma та Server Utils
Серверні утиліти в server/utils/ автоматично імпортуються у весь серверний код, роблячи клієнти баз даних та спільну логіку доступними без явних імпортів.
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
}З глобально доступним клієнтом бази даних route handlers отримують до нього прямий доступ:
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 для ініціалізації runtime
Серверні плагіни в server/plugins/ виконуються один раз при запуску сервера, ідеально підходячи для ініціалізації з'єднань, планування задач або налаштування моніторингу.
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')
})
})Система плагінів інтегрується з хуками Nitro для управління життєвим циклом. Хуки спрацьовують у певних точках: request перед обробкою, beforeResponse перед відправленням та close під час завершення роботи.
Типобезпечні API виклики з Vue компонентів
Утиліта $fetch в Nuxt забезпечує виведення типів із серверних routes при використанні аліаса ~/server. У поєднанні з composable useFetch компоненти споживають API з повною підтримкою 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>Стратегії кешування для Server Routes
Nuxt 4.3 впроваджує покращені елементи керування кешуванням через routeRules в nuxt.config.ts. Server routes використовують ту саму інфраструктуру кешування, що й сторінки.
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 }
}
})Для динамічної інвалідації кешу використовується wrapper 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'
}
})Обробка помилок та форматування відповідей
Послідовні відповіді про помилки покращують зручність використання API. Необхідно створити спільну утиліту для обробки помилок:
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'
})
}Для комплексних Vue.js патернів та управління станом варто ознайомитися зі статтею порівняння Pinia vs Vuex.
Перед розгортанням серверів Nitro необхідно: валідувати змінні середовища схемами Zod, впровадити rate limiting middleware, додати логування запитів для налагодження та налаштувати CORS заголовки для cross-origin доступу до API.
Розгортання на різних платформах
Система пресетів Nitro генерує оптимізовані збірки для кожної платформи:
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']
}
}
})Для Node.js розгортань вихідні дані включають автономний сервер:
# Build for production
npm run build
# Start the server
node .output/server/index.mjsNuxt 3 досягає завершення підтримки 31 липня 2026 року. Проекти повинні мігрувати на Nuxt 4 використовуючи офіційний посібник з міграції. Nuxt 5 з Nitro v3 з'явиться незабаром після цього.
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Підсумок
- Server routes в
server/api/автоматично відображаються на/api/*endpoints з суфіксами HTTP методів (.get.ts,.post.ts), що контролюють типи запитів - Middleware в
server/middleware/обробляє автентифікацію, логування та трансформацію запитів перед виконанням routes - Об'єкт
event.contextспільно використовує типізовані дані між middleware та handlers в межах запиту - Серверні утиліти в
server/utils/автоматично імпортуються в серверний код, ідеально підходячи для клієнтів баз даних та спільної логіки - Nuxt 4 приймає іменування Web API (
status/statusText) в підготовці до Nitro v3 defineCachedEventHandlerзабезпечує кешування на рівні routes з контролем інвалідації- Пресети Nitro дозволяють безконфігураційне розгортання на Vercel, Netlify, Cloudflare та Node.js серверах
Теги
Поділитися
Пов'язані статті

Nuxt 4 у 2026 році: Нова структура каталогів та міграція з Nuxt 3
Повний посібник з міграції на Nuxt 4: нова структура app/, singleton-шар отримання даних, поверхнева реактивність за замовчуванням, розділення TypeScript-контексту, нормалізовані імена компонентів, Vue Router v5, зміни в управлінні head та контрольний список міграції.

Просунуті Vue 3 Composables: патерни повторного використання та питання для співбесіди 2026
Вичерпний посібник з просунутих Vue 3 Composables: патерни повторного використання, асинхронна обробка помилок, Dependency Injection, валідація форм та актуальні питання для технічних співбесід у 2026 році.

Тестування Vue 3 у 2026 році: Vitest, Vue Test Utils та питання співбесід
Практичний посібник із тестування Vue у 2026 році: налаштування Vitest, монтування компонентів через Vue Test Utils, перевірка композаблів і сховищ Pinia, мокування API, вимірювання покриття та питання, які ставлять команди на співбесідах.