# Nuxt 3: SSR і статична генерація, повний посібник > Опанувати SSR і статичну генерацію з Nuxt 3. Від useFetch до route rules: як оптимізувати продуктивність застосунків Vue.js. - Published: 2026-02-11 - Updated: 2026-04-28 - Author: SharpSkill - Tags: nuxt 3, vue.js, ssr, статична генерація, веб-продуктивність - Reading time: 12 min --- Nuxt 3 змінює спосіб створення застосунків Vue.js, пропонуючи кілька режимів рендерингу, що пасують до різних сценаріїв. Від Server-Side Rendering (SSR) до статичної генерації та гібридного рендерингу — фреймворк надає виняткову гнучкість для оптимізації продуктивності та SEO. > **Передумови** > > Цей посібник передбачає базові знання Vue 3 та Composition API. Знайомство з концепціями серверного рендерингу буде корисним, але не обов'язковим, оскільки основи пояснюються по ходу матеріалу. ## Розуміння режимів рендерингу Nuxt 3 Перед тим як занурюватися в код, важливо зрозуміти відмінності між доступними режимами рендерингу. Кожен режим відповідає на конкретні потреби щодо продуктивності, SEO та користувацького досвіду. SSR (Server-Side Rendering) генерує HTML на сервері для кожного запиту. Статична генерація (SSG) попередньо генерує всі сторінки на етапі збірки. Гібридний режим дозволяє поєднувати ці підходи посторінково. ```typescript // nuxt.config.ts // Конфігурація різних режимів рендерингу export default defineNuxtConfig({ // SSR увімкнено за замовчуванням (рекомендовано для SEO) ssr: true, // Статична генерація: попередньо рендерить усі сторінки // Використовуйте 'npm run generate' для збірки // target: 'static', // Синтаксис Nuxt 2 // Гібридний режим: налаштовується для кожного маршруту routeRules: { // Головна сторінка: попередньо рендериться та кешується '/': { prerender: true }, // Блог: статична генерація '/blog/**': { prerender: true }, // Dashboard: рендеринг лише на клієнті '/dashboard/**': { ssr: false }, // API: без попереднього рендерингу '/api/**': { prerender: false } } }) ``` Ця конфігурація демонструє силу гібридного режиму: кожна частина застосунку використовує найбільш відповідний для своїх потреб режим рендерингу. ## Отримання даних із useFetch і useAsyncData Nuxt 3 надає два основні composables для ізоморфного отримання даних. Вони працюють як на сервері, так і на клієнті, з автоматичним керуванням гідратацією. `useFetch` — це обгортка над `useAsyncData`, що спрощує HTTP-виклики. `useAsyncData` дає більше контролю в розширених сценаріях. ```vue ``` Для випадків, що потребують більшого контролю, `useAsyncData` дозволяє виконати будь-яку асинхронну функцію. ```vue ``` Ці composables запобігають подвійному отриманню даних: дані, отримані на сервері, серіалізуються в HTML-payload і повторно використовуються під час гідратації на клієнті. ## Налаштування SSR за допомогою server hooks SSR у Nuxt 3 можна налаштувати через server hooks. Ці хуки дозволяють втручатися на різних етапах циклу рендерингу, щоб змінити стандартну поведінку. ```typescript // server/plugins/render-hooks.ts // Серверний плагін для кастомізації SSR-рендерингу export default defineNitroPlugin((nitroApp) => { // Хук, що виконується перед рендерингом кожної сторінки nitroApp.hooks.hook('render:html', (html, { event }) => { // Інжекція скриптів або метаданих html.head.push(` `) }) // Хук для керування кешем рендерингу nitroApp.hooks.hook('render:response', (response, { event }) => { // Додавання кастомних заголовків кешу const path = event.path if (path.startsWith('/blog/')) { // Тривалий кеш для статей блогу response.headers['Cache-Control'] = 'public, max-age=3600, s-maxage=86400' } else if (path.startsWith('/api/')) { // Без кешу для API response.headers['Cache-Control'] = 'no-store' } }) }) ``` > **Продуктивність SSR** > > Хук `render:response` ідеально підходить для впровадження стратегій HTTP-кешу. Поєднання SSR із CDN, який поважає заголовки Cache-Control, дозволяє віддавати попередньо відрендерені сторінки, зберігаючи можливість їх інвалідації. ## Статична генерація з nuxt generate Статична генерація заздалегідь будує всі сторінки на етапі збірки. Цей підхід ідеальний для сайтів зі стабільним контентом — блогів, документації або маркетингових сайтів. Для динамічних маршрутів Nuxt має знати всі URL, які треба згенерувати. Хук `prerender:routes` дозволяє визначати ці маршрути програмно. ```typescript // nuxt.config.ts // Повна конфігурація для статичної генерації export default defineNuxtConfig({ // Увімкнути статичну генерацію nitro: { prerender: { // Увімкнути автоматичне сканування посилань crawlLinks: true, // Маршрути, які завжди потрібно включати routes: ['/', '/about', '/contact'], // Ігнорувати певні маршрути ignore: ['/admin', '/api'] } }, hooks: { // Хук для генерації динамічних маршрутів async 'prerender:routes'(ctx) { // Отримання статей з API або БД const articles = await fetch('https://api.example.com/articles') .then(res => res.json()) // Додавання маршрутів статей for (const article of articles) { ctx.routes.add(`/blog/${article.slug}`) } // Отримання категорій const categories = await fetch('https://api.example.com/categories') .then(res => res.json()) for (const category of categories) { ctx.routes.add(`/category/${category.slug}`) } } } }) ``` Для проєктів із багатьма сторінками автоматичний crawler може бути недостатнім. Ось більш надійний підхід з окремим конфігураційним файлом. ```typescript // server/utils/generate-routes.ts // Утиліта для генерації списку динамічних маршрутів import { prisma } from './prisma' export async function getAllStaticRoutes(): Promise { const routes: string[] = [] // Статті блогу const articles = await prisma.article.findMany({ where: { published: true }, select: { slug: true, category: { select: { slug: true } } } }) for (const article of articles) { routes.push(`/blog/${article.category.slug}/${article.slug}`) } // Сторінки продуктів const products = await prisma.product.findMany({ where: { active: true }, select: { slug: true } }) for (const product of products) { routes.push(`/products/${product.slug}`) } // Сторінки тегів const tags = await prisma.tag.findMany({ select: { slug: true } }) for (const tag of tags) { routes.push(`/tags/${tag.slug}`) } return routes } ``` ## Гібридний рендеринг із routeRules Гібридний рендеринг — флагманська функція Nuxt 3. Він дозволяє визначати різні правила рендерингу для кожного маршруту, поєднуючи переваги SSR та SSG. ```typescript // nuxt.config.ts // Розширена конфігурація гібридного рендерингу export default defineNuxtConfig({ routeRules: { // Маркетингові сторінки: попередньо відрендерені та довго кешовані '/': { prerender: true }, '/pricing': { prerender: true }, '/features/**': { prerender: true }, // Блог: ISR (Incremental Static Regeneration) // Ревалідація щогодини '/blog/**': { isr: 3600, prerender: true }, // Документація: CDN-кеш з ревалідацією '/docs/**': { swr: 86400, // Stale-while-revalidate prerender: true }, // E-commerce: SSR з коротким кешем '/products/**': { ssr: true, cache: { maxAge: 60, staleMaxAge: 300 } }, // Кошик і checkout: лише на клієнті '/cart': { ssr: false }, '/checkout/**': { ssr: false }, // Dashboard: режим SPA '/dashboard/**': { ssr: false, // Вимкнути попередній рендеринг prerender: false }, // API маршрути: без кешу за замовчуванням '/api/**': { cors: true, headers: { 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE' } } } }) ``` Ця конфігурація ілюструє типову архітектуру сучасного застосунку: публічні сторінки оптимізуються для SEO за допомогою SSG, тоді як інтерактивні розділи використовують клієнтський рендеринг. ## Оптимізація продуктивності з кешем даних Окрім кешу сторінок, Nuxt 3 дозволяє кешувати отримані дані. Ця стратегія знижує навантаження на API та покращує час відповіді. ```typescript // server/api/articles/[slug].get.ts // API-ендпоінт із кешем даних import { getArticleBySlug } from '~/server/utils/articles' export default defineCachedEventHandler( async (event) => { const slug = getRouterParam(event, 'slug') if (!slug) { throw createError({ statusCode: 400, message: 'Відсутній slug' }) } const article = await getArticleBySlug(slug) if (!article) { throw createError({ statusCode: 404, message: 'Статтю не знайдено' }) } return article }, { // Ключ кешу на основі slug getKey: (event) => `article-${getRouterParam(event, 'slug')}`, // Тривалість кешу: 1 година maxAge: 3600, // Stale-while-revalidate: віддавати застарілий кеш під час оновлення staleMaxAge: 7200, // Інвалідація на основі тегів tags: ['articles'] } ) ``` Для інвалідації кешу при зміні контенту Nuxt надає систему тегів. ```typescript // server/api/articles/[slug].put.ts // Оновлення статті з інвалідацією кешу import { updateArticle } from '~/server/utils/articles' export default defineEventHandler(async (event) => { const slug = getRouterParam(event, 'slug') const body = await readBody(event) // Оновлення статті const article = await updateArticle(slug, body) // Інвалідація кешу для цієї статті await useStorage('cache').removeItem(`nitro:handlers:article-${slug}`) // Або інвалідація на основі тегів (всі статті) // await useStorage('cache').clear('articles') return article }) ``` > **Розподілений кеш** > > У продакшені з кількома інстансами кеш у пам'яті недостатній. Рекомендується налаштувати Redis або іншу розподілену систему через конфігурацію Nitro, щоб забезпечити узгодженість між інстансами. ## Керування SEO та метаданими SSR дозволяє оптимізувати SEO, генеруючи метадані на сервері. Nuxt 3 пропонує кілька підходів до динамічного керування meta tag'ами. ```vue ``` Для статичних сторінок метадані можна визначати безпосередньо в компоненті. ```vue ``` ## Розгортання та виробничі міркування Вибір способу розгортання залежить від обраного режиму рендерингу. Ось основні варіанти та їхні конфігурації. ```typescript // nuxt.config.ts // Конфігурація для різних середовищ розгортання export default defineNuxtConfig({ nitro: { // Preset відповідно до цільової платформи // preset: 'vercel', // Vercel // preset: 'netlify', // Netlify // preset: 'cloudflare-pages', // Cloudflare // preset: 'node-server', // Класичний Node.js // Конфігурація для Node.js у продакшені preset: 'node-server', // Стиснення відповідей compressPublicAssets: true, // Конфігурація сховища кешу storage: { cache: { driver: 'redis', url: process.env.REDIS_URL } } }, // Змінні середовища під час виконання runtimeConfig: { // Секрети (не доступні клієнту) apiSecret: process.env.API_SECRET, // Публічна конфігурація public: { apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api' } } }) ``` Для статичного розгортання команда `npm run generate` створює папку `.output/public`, готову до розміщення на будь-якому хостингу статичних файлів. ```bash # Статична генерація npm run generate # Вміст .output/public можна розгорнути на: # - Vercel (автоматичне визначення) # - Netlify (автоматична конфігурація) # - GitHub Pages # - S3 + CloudFront # - Будь-якому CDN або сервері статичних файлів ``` ## Висновок Nuxt 3 пропонує виняткову гнучкість для рендерингу застосунків Vue.js. Вибір між SSR, SSG та гібридним рендерингом залежить від конкретних потреб кожного проєкту. **Ключові висновки:** ✅ **SSR**: ідеально для динамічного контенту, що потребує гарного SEO (e-commerce, новинні сайти) ✅ **SSG**: чудово для стабільного контенту (блоги, документація, маркетингові сайти) ✅ **Гібридний**: найкращий підхід для складних застосунків з різноманітними потребами ✅ **useFetch/useAsyncData**: автоматична гідратація та керування кешем ✅ **routeRules**: точне налаштування поведінки кожного маршруту ✅ **Кешування**: множина стратегій для оптимізації продуктивності в продакшені Поєднання гібридного рендерингу з продуманою стратегією кешування дозволяє створювати продуктивні застосунки, оптимізовані для SEO, зберігаючи інтерактивність Single Page Applications. --- 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-3-ssr-static-generation