логотип PurpleSchool
логотип PurpleSchool

Как работает Server-Side Rendering SSR в Nuxt

Автор

Олег Марков

Введение

Server-Side Rendering (SSR) — это подход к рендерингу веб-приложений, при котором HTML формируется на сервере и отправляется пользователю уже готовым. Это противоположность подходу Client-Side Rendering (CSR), где вся логика происходит на стороне клиента, а сервер отдаёт минимальную HTML-оболочку, а затем браузер самостоятельно загружает и отрисовывает страницу. В экосистеме Vue наиболее популярной реализацией SSR выступает фреймворк Nuxt. Если вы хотите быстрое первое отображение страниц, лучшую индексацию сайта и меньшую нагрузку на клиента — SSR с Nuxt предоставляет удобную и работающую “из коробки” инфраструктуру.

В этой статье я расскажу, как работает SSR в Nuxt. Мы подробно разберём архитектуру, узнаем как Nuxt строит приложение и формирует HTML на сервере, рассмотрим жизненный цикл и ключевые функции, и посмотрим на примеры кода для разных ситуаций. Кроме того, я подскажу, как настраивать SSR-проекты, выделю плюсы и минусы этого подхода, а самые частые технические вопросы объединю в конце вместе с быстрыми советами.

Как устроен SSR в Nuxt

Основы SSR: теория

При SSR запрос пользователя сначала приходит на сервер, где запускается Vue-движок под управлением Nuxt. На сервере выполняется код приложения, собирается готовый HTML-файл страницы (например, домашняя, карточка товара — любая нужная вам страница). Сервер отдаёт вам уже заполненную разметку. Дальше, после загрузки страницы, кода приложения “гидратируется” — это значит, что на клиенте Vue снова “оживляет” полученный HTML и становится способным реагировать на действия пользователя, делать переходы, обновлять данные и прочее.

Принципиальные отличия от CSR

  • SSR: Сервер выдает уже собранный HTML + Vue-состояние. Браузер быстро выводит страницу, а затем подключает JS для работы приложения.
  • CSR: Сервер отдаёт минимальный index.html, браузер скачивает JS-бандлы, после чего рисует содержимое самостоятельно.

Почему это важно

  • Быстрое первое отображение — браузер быстро показывает контент даже на медленных устройствах.
  • SEO — поисковые боты получают нормальный HTML, а не пустую заглушку.
  • Быстрый Time to Interactive — пользователю кажется, что страница живёт мгновенно.

Server-Side Rendering (SSR) — это важная техника, которая позволяет улучшить SEO и ускорить загрузку страниц в Nuxt-приложениях. Понимание того, как работает SSR, и умение его настраивать — это необходимый навык для любого Nuxt-разработчика. Если вы хотите детальнее погрузиться в мир Nuxt, освоить все его тонкости и стать настоящим профессионалом — приходите на наш большой курс Nuxt - fullstack Vue фреймворк. На курсе 129 уроков и 13 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Архитектура Nuxt SSR

Как устроен сервер Nuxt

Когда вы запускаете команду nuxt start (или работаете в dev-режиме), Nuxt создает и запускает собственный сервер (например, используя Node.js). Сервер перехватывает все http-запросы, выбирает нужную страницу с нужными параметрами, вызывает Vue-компоненты, собирает данные и “рендерит” HTML каждой страницы индивидуально.

Жизненный цикл SSR-запроса в Nuxt:

  1. Запрос пользователя — например, GET /product/42.
  2. Маршрутизация — Nuxt определяет, какая страница и компоненты относятся к этому руту.
  3. Вызов server-prefetch/data/fetch — если у компонентов есть асинхронная загрузка данных, она выполняется именно сейчас.
  4. Сбор состояния — все "срезы" Vuex и данные, необходимые странице, инициализируются на сервере.
  5. Рендер HTML — собирается финальный HTML-ответ, встраиваются данные, нужные для гидратации.
  6. Отправка клиенту — браузер получает готовую страницу и статику JS.
  7. Гидратация — приложение “оживляет” разметку на клиенте.

Важные директории

В Nuxt проекте за архитектуру SSR отвечают следующие папки:

  • pages — шаблоны страниц. Каждая соответствует роуту.
  • layouts — общие каркасы для разных шаблонов.
  • store — глобальное хранилище Vuex для данных.
  • middleware — промежуточные скрипты, отрабатывающие на стороне сервера при каждом запросе.
  • plugins — инициализация подключаемых библиотек до рендера приложения.

Способы получения данных для SSR

Метод asyncData

Метод asyncData — ключевой для SSR в Nuxt. Он вызывается перед отображением компонента (и на сервере, и на клиенте), позволяя загрузить все нужные данные заранее. Важно: он работает только в компонентах-страницах в папке pages.

Пример:

// pages/users/_id.vue
export default {
  async asyncData({ params, $axios }) {
    // Загрузка данных пользователя на сервере до рендеринга страницы
    const user = await $axios.$get(`/api/users/${params.id}`)
    return { user } // Эти данные попадут в props компонента
  }
}

Как видите, SSR Nuxt гарантирует, что данные будут доступны ещё на этапе рендеринга HTML. Сервер сам "подставит" нужное значение и отдаст ваш контент поисковикам и пользователям.

Метод fetch

Этот метод похож на asyncData, но работает и в сторонах компонентов (не только в pages). Он не возвращает данные напрямую, а обновляет состояние через commit или dispatch.

export default {
  async fetch({ store, params }) {
    // Асинхронная загрузка данных для сторы, пока страница рендерится на сервере
    await store.dispatch('fetchUser', params.id)
  }
}

Пример работы SSR: разбираем шаги

Настройка проекта с SSR в Nuxt

По умолчанию,Nuxt работает в SSR-режиме (universal), что видно в файле nuxt.config.js:

export default {
  ssr: true, // universal rendering (default)
}

Если эта опция включена, Nuxt сам настраивает рендерер для сервера и клиента.

Пошаговый пример: создание страницы с SSR

  1. Создаём страницу:
// pages/post/_id.vue
export default {
  async asyncData({ params, $axios }) {
    const post = await $axios.$get(`/api/posts/${params.id}`)
    return { post }
  }
}
  1. Используем данные в шаблоне:
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.body }}</p>
  </div>
</template>
  1. Сервер отдаёт пользователю построенный HTML:
<!DOCTYPE html>
<html>
  <head>
    <!-- meta-теги генерация nuxt -->
  </head>
  <body>
    <div id="__nuxt">
      <div>
        <h1>Заголовок поста</h1>
        <p>Текст поста...</p>
      </div>
    </div>
    <script src="/_nuxt/....js"></script>
  </body>
</html>

Здесь вы видите: HTML страницы наполнен содержимым, хотя пользователь открыл его впервые.

Подробнее о гидратации (Hydration)

Гидратация — процесс, когда клиентский JavaScript "оживляет" уже сгенерированную разметку, чтобы страницы стали интерактивны. Именно после этой фазы вы сможете кликать по кнопкам, отправлять формы и переходить между страницами без полной перезагрузки.

  • На сервере сгенерирован HTML и сериализованы все необходимые данные.
  • После загрузки, клиент загружает JS-бандлы и запускает Vue.
  • Vue "подхватывает" структуру страницы, синхронизируется с исходным состоянием и позволяет реагировать на действия пользователя.

Как работает кеширование и оптимизация SSR

При большом количестве пользователей сервер может испытать нагрузки из-за постоянного рендеринга страниц. Nuxt позволяет оптимизировать SSR:

Использование кеша

Для кеширования страниц можно интегрировать внешние сервисы (например, Redis, memcached) или плагины, либо воспользоваться встроенной возможностью SSR-кеша.

Простой пример подключения кеша через модуль nuxt-ssr-cache:

// nuxt.config.js
modules: [
  'nuxt-ssr-cache'
],
cache: {
  useHostPrefix: false,
  pages: [
    // Кешировать все страницы блога на 1 минуту
    /^\/blog\/.*$/
  ],
  store: {
    type: 'memory',
    max: 100,
    ttl: 60
  }
}

Теперь Nuxt будет хранить сгенерированные HTML-файлы в оперативной памяти и быстро отдавать их на повторные запросы, сокращая время отклика сервера.

Динамические данные и инвалидация кеша

Если страница содержит часто обновляемые данные, вам нужно тщательно продумывать механику очистки кеша (например, при публикации новости страница должна сбрасываться).

SSR и статика: отличие от SSG в Nuxt

Стоит различать SSR (server-side rendering) и SSG (static site generation). В SSG-подходе (режим nuxt generate), Nuxt собирает HTML-страницы во время сборки проекта, а не при каждом запросе, отдавая их как статические файлы. SSR генерирует HTML по запросу на лету. Вот как включается режим SSG:

export default {
  target: 'static' // В этом случае SSR выключается, включается SSG
}

SSR — динамическое, SSG — статическое. Выбирать стоит исходя из целей проекта: если данные не часто меняются, SSG быстрее и дешевле.

Использование middleware и серверных хуков

С помощью middleware вы можете реализовать дополнительную обработку запросов на серверном этапе: авторизация, редиректы, логгирование.

// middleware/auth.js
export default function ({ store, redirect }) {
  // Проверяем наличие авторизации
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}

В файле страницы или глобальной middleware подключаете:

// for page
middleware: 'auth'

Работа с окружением: данные, доступные только на сервере

Внутри SSR вы имеете доступ к Node.js API. Вы можете считывать защищённые переменные окружения, обращаться к приватным API или базе данных. На клиенте эти данные недоступны — это повышает безопасность.

Пример:

async asyncData({ env }) {
  // К env.foo можно обратиться только на сервере
  return { foo: process.env.SECRET_TOKEN }
}

Не забывайте, что любые данные, возвращаемые из asyncData, попадут в HTML-код страницы, т.е. не передавайте в шаблон токены и пароли — только используйте их для внутренних серверных запросов.

Особенности и ограничения SSR в Nuxt

Возможные минусы

  • Повышается нагрузка на сервер — ресурсозатратно рендерить каждую страницу при каждом запросе.
  • Архитектура сложнее: все ошибки SSR могут сломать загрузку страницы.
  • Сторонние пакеты, рассчитанные только на client-side, могут вызвать run-time ошибки при SSR.

Зоны риска

  • Использование window, document, navigator в коде компонентов — это не будет работать на сервере.
  • Асинхронные операции должны заканчиваться до финального рендера, иначе страница не будет содержать ожидаемых данных.
  • Если питание данных зависит только от client-side (например, через localStorage), в SSR такого не будет.

SSR с внешними API и безопасностью

Из-за того, что в SSR сервер выступает “клиентом” для внешних API, вы можете не беспокоиться о CORS (с сервером почти всегда нет подобных проблем). Это позволяет скрывать внутренние ключи API от пользователя. Хорошая практика — запрашивать чувствительные данные только с сервера, отдавая в клиент только необходимые части информации.

SSR vs SPA: когда стоит использовать SSR

Рассмотрим ситуации, для которых SSR подходит идеально:

  • SEO-критичные сайты (блоги, новостные порталы, магазины).
  • Публичные страницы, важна быстрая загрузка первого экрана.
  • Сайты с частой или массовой публикацией новых материалов.

А вот где SSR использовать сложнее:

  • Внутренние системы, где нет требований по SEO и быстрому первому отображению.
  • Одностраничники, где все работает на стороне клиента.
  • Приложения с высокой нагрузкой на чтение частных профилей и много пользовательских сессий (требуется продуманная оптимизация кеша).

Заключение

Nuxt реализует полноценный SSR-прослойку для Vue-приложений, делая ваш проект быстрым, удобным и SEO-френдли “из коробки”. При правильной архитектуре вы получаете одновременное преимущество динамических страниц, хорошей индексации, а также большой гибкости при работе с внешними API и защищёнными данными. SSR в Nuxt многое делает автоматически, но требует понимания некоторых нюансов: где грузить данные, как защищаться от ошибок, какие методы доступны только на “сервере”.

Server-Side Rendering (SSR) — это лишь одна из техник, которые позволяют улучшить производительность и SEO Nuxt-приложения. Чтобы создавать профессиональные веб-приложения, необходимо освоить множество других навыков, таких как оптимизация клиентской части, кэширование данных, настройка серверной части и мониторинг производительности. На курсе Nuxt - fullstack Vue фреймворк вы получите комплексные знания и практический опыт, необходимые для создания профессиональных веб-приложений на Nuxt. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир Nuxt прямо сегодня.

Частозадаваемые технические вопросы по теме и ответы на них

Как реализовать SSR-авторизацию с токенами в Nuxt?

Чтобы реализовать авторизацию с использованием токенов на этапе SSR, храните токен в httpOnly cookie. В middleware читайте куку и при необходимости отправляйте её с серверными запросами. Пример:

// middleware/auth.js
export default function({ req, redirect }) {
  const token = req && req.headers.cookie ? // получаем токен из cookie
    req.headers.cookie.split('token=')[1] : null
  if (!token) redirect('/login')
}

Как получить доступ к Node модулям только на сервере в Nuxt?

В коде проверяйте окружение:

if (process.server) {
  // Здесь можно импортировать fs, path и другие модули Node
  const fs = require('fs')
}

Такой код не попадёт в бандлы клиента.

Как SSR влияет на работу с localStorage или sessionStorage?

Эти API браузера недоступны на сервере. В компоненте проверяйте окружение:

if (process.client) {
  localStorage.setItem('foo', 'bar')
}

Как отследить ошибки SSR и вывести их пользователю?

Используйте хуки error в Nuxt:

export default {
  async asyncData({ error }) {
    try {
      // загрузка данных
    } catch (e) {
      error({ statusCode: 500, message: 'Ошибка загрузки данных' })
    }
  }
}

Как реализовать SSR только для отдельных страниц, а остальные оставить как SPA?

В Nuxt 2 нельзя изолировать страницы по типу рендеринга — весь проект работает как universal или SPA. В Nuxt 3 можно использовать middleware, чтобы для определённых роутов возвращать SSR или SSG режим. Для сложных случаев используйте SSR для публичных страниц, а личный кабинет выносите в отдельный SPA-проект.

Стрелочка влевоКак запустить Nuxt-приложение в productionНастройка и оптимизация серверной части Nuxt-приложенияСтрелочка вправо

Постройте личный план изучения Nuxt до уровня Middle — бесплатно!

Nuxt — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Nuxt

Генерация статического сайта с помощью NuxtКак использовать useAsyncData в NuxtКак использовать SVG в NuxtКоманды для запуска NuxtРабота с JSON-данными в NuxtКак настроить HTML-шаблон в NuxtГенерация статического сайта с помощью NuxtРуководство по получению данных с Fetch в NuxtКак отключить определенные функции в NuxtРабота с данными в Nuxt с помощью useNuxtDataНастройка и использование cookie в NuxtГайд по аутентификации (auth) в NuxtКак создавать API-маршруты в Nuxt
Использование Vite для ускорения разработки в NuxtРуководство по использованию TypeScript в NuxtКак запустить Nuxt-приложение в productionКак работает Server-Side Rendering SSR в NuxtНастройка и оптимизация серверной части Nuxt-приложенияРуководство по настройке маршрутизации в NuxtКакие проекты разумно реализовывать на NuxtИнструкция по управлению пакетами NPM в NuxtИнтеграция Node.js для Nuxt-приложенияНастройка мета-тегов для SEO в NuxtНастройка и использование HTTPS в NuxtКак отлавливать и обрабатывать ошибки в NuxtКак развернуть Nuxt приложение в DockerРуководство по развертыванию приложений в Nuxt CloudКак оптимизировать сборку на NuxtИнтеграция Laravel и Nuxt
Открыть базу знаний

Лучшие курсы по теме

Иконка ракетыСкоро!
изображение курса

Nuxt

Антон Ларичев
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий