Олег Марков
Как работает 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:
- Запрос пользователя — например, GET /product/42.
- Маршрутизация — Nuxt определяет, какая страница и компоненты относятся к этому руту.
- Вызов server-prefetch/data/fetch — если у компонентов есть асинхронная загрузка данных, она выполняется именно сейчас.
- Сбор состояния — все "срезы" Vuex и данные, необходимые странице, инициализируются на сервере.
- Рендер HTML — собирается финальный HTML-ответ, встраиваются данные, нужные для гидратации.
- Отправка клиенту — браузер получает готовую страницу и статику JS.
- Гидратация — приложение “оживляет” разметку на клиенте.
Важные директории
В 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
- Создаём страницу:
// pages/post/_id.vue
export default {
async asyncData({ params, $axios }) {
const post = await $axios.$get(`/api/posts/${params.id}`)
return { post }
}
}
- Используем данные в шаблоне:
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
</div>
</template>
- Сервер отдаёт пользователю построенный 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 до уровня Middle — бесплатно!
Nuxt — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Nuxt
Лучшие курсы по теме

Nuxt
Антон Ларичев
TypeScript с нуля
Антон Ларичев