# 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 ``` ## Стратегії кешування для 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