# Nuxt Nitro та Server Routes у 2026: Full-Stack Vue та API Endpoints
> Опануйте Nuxt Nitro server routes для створення full-stack Vue застосунків. Дізнайтеся про API endpoints, middleware, інтеграцію з базою даних та патерни production deployment з Nuxt 4.
- Published: 2026-07-16
- Updated: 2026-07-16
- Author: SharpSkill
- Tags: nuxt, nitro, vue, full-stack, api, server-routes
- Reading time: 12 min
---
Nuxt Nitro перетворює Vue застосунки на повноцінні full-stack рішення, надаючи універсальний серверний движок, який обробляє API routes, middleware та серверну логіку поряд із фронтенд компонентами. З Nuxt 4.3 та майбутнім Nitro v3 створення production-ready бекендів ніколи не було настільки інтегрованим з Vue розробкою.
> **Full-Stack в одному репозиторії**
>
> Nitro дозволяє спільно використовувати TypeScript типи між фронтендом та бекендом, усуваючи розбіжності API контрактів та зменшуючи boilerplate код. Server routes знаходяться в `server/api/` і автоматично стають доступними як `/api/*` endpoints.
## Архітектура серверного движка Nuxt Nitro
Nitro служить універсальним JavaScript серверним середовищем виконання, що забезпечує роботу директорії server в Nuxt. На відміну від традиційних Node.js серверів, Nitro компілює оптимізовані під платформу bundle'и, які безперешкодно розгортаються на [Vercel](https://vercel.com/docs/frameworks/nuxt), [Netlify](https://docs.netlify.com/frameworks/nuxt/), Cloudflare Workers та стандартних Node.js середовищах без змін у коді.
Архітектура розділяє відповідальності через конвенції директорій:
```typescript
// server/api/users.get.ts
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.
```typescript
// server/api/products/[id].get.ts
// 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:
```typescript
// server/api/products/index.post.ts
// 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 не повертає відповіді безпосередньо.
```typescript
// server/middleware/auth.ts
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 в межах одного запиту, забезпечуючи типобезпечний спосіб обміну даними. Типи контексту визначаються у файлі декларацій:
```typescript
// server/types/context.d.ts
declare module 'h3' {
interface H3EventContext {
user?: {
id: string
email: string
role: 'admin' | 'user'
}
}
}
```
Для підготовки до співбесід щодо концепцій Nuxt server варто ознайомитися з модулем [питань на співбесіду про Nuxt Server Routes](/technologies/vue-nuxt/interview-questions/nuxt-server-routes).
## Інтеграція бази даних з Prisma та Server Utils
Серверні утиліти в `server/utils/` автоматично імпортуються у весь серверний код, роблячи клієнти баз даних та спільну логіку доступними без явних імпортів.
```typescript
// server/utils/db.ts
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 отримують до нього прямий доступ:
```typescript
// server/api/posts/index.get.ts
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/` виконуються один раз при запуску сервера, ідеально підходячи для ініціалізації з'єднань, планування задач або налаштування моніторингу.
```typescript
// server/plugins/database.ts
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](https://nitro.unjs.io/guide/plugins) для управління життєвим циклом. Хуки спрацьовують у певних точках: `request` перед обробкою, `beforeResponse` перед відправленням та `close` під час завершення роботи.
## Типобезпечні API виклики з Vue компонентів
Утиліта `$fetch` в Nuxt забезпечує виведення типів із серверних routes при використанні аліаса `~/server`. У поєднанні з [composable useFetch](/technologies/vue-nuxt/interview-questions/nuxt-data-fetching) компоненти споживають API з повною підтримкою TypeScript.
```vue
Loading...
{{ error.message }}
```
## Стратегії кешування для Server Routes
Nuxt 4.3 впроваджує покращені елементи керування кешуванням через `routeRules` в `nuxt.config.ts`. Server routes використовують ту саму інфраструктуру кешування, що й сторінки.
```typescript
// nuxt.config.ts
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`:
```typescript
// server/api/trending.get.ts
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. Необхідно створити спільну утиліту для обробки помилок:
```typescript
// server/utils/errors.ts
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](/blog/vue-nuxt/vue-3-pinia-vs-vuex-state-management).
> **Чекліст для production**
>
> Перед розгортанням серверів Nitro необхідно: валідувати змінні середовища схемами Zod, впровадити rate limiting middleware, додати логування запитів для налагодження та налаштувати CORS заголовки для cross-origin доступу до API.
## Розгортання на різних платформах
Система пресетів Nitro генерує оптимізовані збірки для кожної платформи:
```typescript
// nuxt.config.ts
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 розгортань вихідні дані включають автономний сервер:
```bash
# Build for production
npm run build
# Start the server
node .output/server/index.mjs
```
> **Завершення підтримки Nuxt 3**
>
> Nuxt 3 досягає завершення підтримки 31 липня 2026 року. Проекти повинні мігрувати на Nuxt 4 використовуючи [офіційний посібник з міграції](https://nuxt.com/docs/getting-started/upgrade). 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 серверах
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/uk/blog/vue-nuxt/nuxt-nitro-server-routes-2026