Навигация

Режимы рендеринга в Nuxt 3

Nuxt 3 позволяет гибко управлять тем, где и когда рендерится HTML: на сервере при каждом запросе, во время сборки, в браузере или по гибридной схеме. Правильный выбор режима влияет на SEO, время до первого контента, нагрузку на сервер и сложность инфраструктуры.

В этой статье разберём SSR, SSG, CSR, ISR и SWR, настройки ssr, prerender, routeRules, а также механизм гидратации Vue-приложения — ключевой процесс, который связывает серверный HTML с интерактивным клиентским приложением.

Общие концепции методов рендеринга без привязки к фреймворку разобраны в статье Методы рендеринга раздела «Производительность». Здесь — реализация в Nuxt 3: routeRules, prerender, ssr и гидратация.

Содержание

  1. Обзор режимов рендеринга
  2. SSR — Server-Side Rendering
  3. CSR — Client-Side Rendering
  4. SSG — Static Site Generation
  5. ISR — Incremental Static Regeneration
  6. SWR — stale-while-revalidate
  7. Гибридный рендеринг через routeRules
  8. Глобальная настройка через ssr
  9. Гидратация Vue-приложения
  10. Как выбрать режим рендеринга
  11. Лучшие практики и антипаттерны
  12. Ключевые тезисы для интервью
  13. Заключение
  14. Полезные ссылки

Обзор режимов рендеринга

РежимКогда рендеритсяГде выполняетсяПодходит для
SSRНа каждый запросСерверДинамических сайтов с SEO: маркетплейсы, соцсети, дашборды
SSGВо время сборкиСборщикДокументация, блоги, лендинги, сайты с редко меняющимся контентом
CSRВ браузереКлиентАдминки, SPA, приложения без требований к SEO
ISRПри первом запросе + фоновое обновлениеСервер/сборщикБлоги, каталоги, страницы с контентом, который обновляется периодически
SWRКэш на сервере + фоновое обновлениеСерверДанные, допускающие кратковременное устаревание

Nuxt 3 позволяет комбинировать эти режимы на уровне отдельных маршрутов через routeRules. Это значит, что главная страница может быть SSG, админка — CSR, а каталог товаров — ISR в рамках одного приложения.


SSR — Server-Side Rendering

По умолчанию Nuxt 3 рендерит HTML на сервере для каждого входящего запроса. Браузер получает готовую страницу, что улучшает SEO, первую отрисовку и поведение в социальных сетях.

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true, // значение по умолчанию
});

Как работает SSR в Nuxt

  1. Серверный движок Nitro получает запрос.
  2. Выполняется код Vue-компонентов и composables на сервере.
  3. useFetch / useAsyncData загружают данные на сервере.
  4. Vue рендерит HTML-строку.
  5. HTML отправляется клиенту вместе с данными гидратации.
  6. В браузере Vue «оживляет» статический HTML, добавляя реактивность и обработчики событий.

Преимущества SSR

  • Хороший SEO и индексация поисковиками.
  • Быстрая первая отрисовка (FCP).
  • Корректные Open Graph и Twitter Card превью.
  • Работа даже при отключённом или медленном JavaScript на этапе загрузки.

Недостатки SSR

  • Серверная нагрузка растёт с трафиком.
  • Нужен сервер или serverless-окружение.
  • Опасность утечек памяти и ошибок, связанных с window/document.

CSR — Client-Side Rendering

При ssr: false Nuxt работает как обычное Vue SPA. Сервер отдаёт минимальный HTML, а рендеринг происходит в браузере.

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
});

Когда применять CSR

  • Админ-панели и внутренние инструменты.
  • Приложения, где SEO не важен.
  • Сложные интерактивные интерфейсы с большим количеством клиентского состояния.

Особенности

  • useFetch и useAsyncData выполняют запросы уже в браузере, после монтирования.
  • Первая загрузка может быть медленнее, чем у SSR.
  • Не требуется серверный рендеринг — можно развернуть на статическом хостинге.

SSG — Static Site Generation

npx nuxi generate

Команда nuxi generate предварительно рендерит все страницы во время сборки и кладёт готовые HTML-файлы в .output/public/. Результат можно разместить на любом статическом хостинге: Netlify, Vercel, GitHub Pages, S3.

Пример

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },
    '/about': { prerender: true },
  },
});
npx nuxi generate

Что попадает в SSG

  • Страницы, доступные во время сборки.
  • Статические данные, полученные через useFetch / useAsyncData при генерации.

Ограничения SSG

  • Динамические маршруты с параметрами нужно перечислить через nitro.prerender.routes или generate.routes.
  • Контент обновляется только при новой сборке (если не используется ISR).
  • Любые данные, недоступные во время сборки, придётся загружать на клиенте.
// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/users/1', '/users/2', '/users/3'],
    },
  },
});

ISR — Incremental Static Regeneration

ISR кэширует статически сгенерированную страницу на заданное время. При первом запросе страница может генерироваться или браться из кэша; по истечении TTL она обновляется в фоне при следующем запросе.

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { isr: 60 }, // кэш 60 секунд
  },
});

Как работает ISR

  • Первый посетитель получает страницу из кэша или триггерит генерацию.
  • Пока TTL не истёк, отдаётся закэшированная версия.
  • После истечения TTL следующий запрос возвращает старую версию и запускает фоновое обновление.

ISR без TTL

export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { isr: true }, // вечный кэш до ручной инвалидации
  },
});

Такой подход похож на SSG, но позволяет генерировать страницы лениво, по запросу.


SWR — stale-while-revalidate

SWR похож на ISR, но работает на уровне серверного ответа: сервер отдаёт закэшированную версию и одновременно обновляет данные в фоне.

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/api/products': { swr: 60 },
    '/products/**': { swr: 300 },
  },
});

ISR vs SWR

ISRSWR
УровеньСтраницаОтвет сервера / API
ПоведениеСтатическая генерация + фоновое обновлениеКэш + фоновое обновление
ПрименениеСтраницы с редкими обновлениямиAPI-эндпоинты, динамические страницы

На практике в Nuxt isr и swr часто дают схожий результат для страниц, но swr более универсален для API.


Гибридный рендеринг через routeRules

routeRules — мощный инструмент для тонкой настройки поведения маршрутов. Правила задаются в nuxt.config.ts и поддерживают glob-пatterns.

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Главная страница — SSG
    '/': { prerender: true },

    // Блог — ISR с обновлением каждые 60 секунд
    '/blog/**': { isr: 60 },

    // Каталог — SWR на 5 минут
    '/products/**': { swr: 300 },

    // Админка — чистый CSR
    '/admin/**': { ssr: false },

    // API — CORS-заголовки
    '/api/**': { cors: true },

    // Редирект
    '/old-page': { redirect: '/new-page' },
  },
});

Основные опции routeRules

ОпцияНазначение
ssr: falseОтключить серверный рендеринг для маршрута.
prerender: trueПредварительно отрендерить страницу при сборке.
isr: number | trueISR с указанным TTL или бессрочно.
swr: number | trueSWR-кэширование ответа.
redirect: stringРедирект на другой URL.
cors: booleanДобавить CORS-заголовки.
headers: objectПроизвольные HTTP-заголовки.
static: booleanСервировать маршрут как статический файл.

routeRules обрабатываются Nitro, поэтому работают независимо от хостинга, если платформа поддерживает соответствующие пресеты.


Глобальная настройка через ssr

Поле ssr в nuxt.config.ts управляет глобальным поведением:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true,  // SSR по умолчанию
  // ssr: false, // полный CSR
});

Приоритет настроек

Более конкретные routeRules переопределяют глобальное значение:

export default defineNuxtConfig({
  ssr: true,
  routeRules: {
    '/admin/**': { ssr: false }, // админка будет CSR, остальное — SSR
  },
});

prerender в dev-режиме

prerender: true в routeRules влияет на production-сборку и nuxi generate. В dev-режиме страницы всё равно рендерятся динамически.


Гидратация Vue-приложения

Гидратация (hydration) — это процесс, при котором Vue берёт серверный HTML и добавляет к нему реактивность, обработчики событий и компонентный жизненный цикл. Без гидратации страница оставалась бы статичной, несмотря на SSR.

Как происходит гидратация

  1. Сервер отдаёт HTML и встроенные данные (__NUXT__).
  2. Браузер загружает JS-бандл.
  3. Vue запускает приложение на существующем DOM.
  4. Vue сравнивает виртуальный DOM с реальным DOM.
  5. Если деревья совпадают, приложение становится интерактивным без перерисовки.
  6. Если есть несоответствие, Vue пытается восстановить состояние и может выдать предупреждение или перерендерить узел.

Проблемы гидратации

Несоответствие серверного и клиентского DOM

Частая причина — использование Date.now(), Math.random() или window при SSR:

<script setup>
// Опасно: на сервере и клиенте будет разное значение
const randomId = Math.random().toString(36);
</script>

Решение — оборачивать клиентский код в <ClientOnly> или проверять process.client:

<template>
  <ClientOnly>
    <RandomWidget />
  </ClientOnly>
</template>
if (process.client) {
  console.log(window.innerWidth);
}

Hydration mismatch

Vue выдаёт предупреждение в консоли:

[Vue warn]: Hydration node mismatch

Причины:

  • Разные данные на сервере и клиенте.
  • Невалидный HTML (например, <div> внутри <p>).
  • Разный рендер в зависимости от process.client / process.server.

Как избежать проблем

  • Не используйте window, document, localStorage на сервере.
  • Инициализируйте случайные значения или даты на клиенте.
  • Проверяйте консоль на предупреждения гидратации в dev-режиме.
  • Используйте <ClientOnly> для компонентов, которые не должны рендериться на сервере.
<template>
  <div>
    <h1>SSR-контент</h1>
    <ClientOnly>
      <ChartComponent />
      <template #fallback>
        <p>Загрузка графика...</p>
      </template>
    </ClientOnly>
  </div>
</template>

Полная гидратация vs частичная

Nuxt 3 по умолчанию выполняет полную гидратацию всего приложения. В будущих версиях и экспериментальных режимах возможны оптимизации вроде частичной или прогрессивной гидратации, но на момент написания статьи это не стандартное поведение.


Как выбрать режим рендеринга

Выбирайте SSR, если

  • Нужен SEO и индексация поисковиками.
  • Контент персонализируется для пользователя.
  • Есть социальные превью и Open Graph.
  • Серверная инфраструктура доступна.

Выбирайте SSG, если

  • Контент меняется редко.
  • Важна максимальная скорость раздачи.
  • Хостинг статический и дешёвый.

Выбирайте ISR, если

  • Контент обновляется, но не мгновенно.
  • Хочется сочетать скорость SSG с актуальностью SSR.

Выбирайте CSR, если

  • Приложение закрытое или административное.
  • SEO не требуется.
  • Важна максимальная интерактивность и сложное клиентское состояние.

Лучшие практики и антипаттерны

✅ Делайте

  • Используйте routeRules для гибкого управления рендерингом по маршрутам.
  • Применяйте prerender: true для лендингов, страниц политики и другого статического контента.
  • Используйте ISR/SWR для страниц с периодически обновляемым контентом.
  • Проверяйте консоль на ошибки гидратации в dev-режиме.
  • Оборачивайте клиентские библиотеки в <ClientOnly> или process.client.
  • Тестируйте production-сборку через nuxi preview, а не только dev-сервер.

❌ Не делайте

  • Не отключайте SSR глобально из-за одной страницы — лучше routeRules.
  • Не используйте window / document в коде, который выполняется на сервере.
  • Не игнорируйте hydration mismatch — они приводят к лишнему ререндеру.
  • Не смешивайте режимы без понимания: CSR-страница не получит SEO-преимуществ SSR.
  • Не забывайте, что nuxi generate и prerender не подходят для данных, меняющихся на каждый запрос.

Ключевые тезисы для интервью

  • Nuxt 3 поддерживает SSR, SSG, CSR, ISR и SWR, которые можно комбинировать через routeRules.
  • SSR по умолчанию — HTML рендерится на сервере для каждого запроса, что даёт SEO и быструю первую отрисовку.
  • CSR (ssr: false) превращает Nuxt в обычное Vue SPA; рендеринг происходит в браузере.
  • SSG (nuxi generate) создаёт статические HTML-файлы во время сборки.
  • ISR кэширует статические страницы и обновляет их в фоне по истечении TTL.
  • SWR кэширует серверный ответ и обновляет его в фоне.
  • routeRules позволяют задавать разные стратегии для разных маршрутов: prerender, isr, swr, ssr: false, redirect, cors.
  • Гидратация связывает серверный HTML с клиентским Vue-приложением; несоответствие DOM вызывает hydration mismatch.
  • Для клиентского кода, несовместимого с сервером, используйте <ClientOnly> или проверку process.client.

Заключение

Понимание режимов рендеринга — основа для построения производительных и SEO-оптимизированных приложений на Nuxt 3. SSR подходит для динамического контента, SSG — для статики, ISR и SWR — для компромисса между скоростью и актуальностью, а CSR — для закрытых инструментов.

routeRules дают возможность гибко настраивать поведение без разделения проекта на несколько приложений. При этом важно следить за гидратацией: серверный HTML и клиентский Vue должны видеть одно и то же дерево DOM, иначе приложение теряет часть преимуществ SSR.

Следующие статьи раздела продолжат погружение: composables и auto-imports, жизненный цикл приложения, серверная часть Nitro, data fetching, состояние и SEO.


Полезные ссылки

  • Nuxt 3 Rendering — официальная документация по режимам рендеринга
  • Nuxt routeRules — настройка правил для маршрутов
  • Nuxt Nitro — документация серверного движка
  • Vue 3 SSR — руководство по SSR в Vue
  • Nuxt Hydration — гидратация и клиентский рендеринг