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

Nuxt JS и Vue 3 для SSR приложений

Автор

Олег Марков

Введение

Nuxt.js – это мощный фреймворк, который существенно облегчает создание серверно-рендеренных (SSR) и статически сгенерированных приложений на базе Vue 3. Именно с помощью Nuxt вы можете буквально за несколько шагов получить полноценное приложение с SEO-оптимизацией, быстрым временем загрузки и продуманной архитектурой.

Vue 3 привнес в Nuxt новые возможности: реактивность на Composition API, улучшенную производительность и поддержку TypeScript. Использование Nuxt позволяет вам не задумываться о ручной настройке маршрутизации, сборке или SSR, поскольку Nuxt берет эти задачи на себя.

В этой статье мы разберем особенности Nuxt.js с Vue 3 для создания SSR-приложений, подробно рассмотрим процесс установки, структуру проекта, работу с маршрутизацией, данными и API, а также завершим примерами кода. Смотрите, я объясню вам как основные концепции, так и небольшие фишки, чтобы вы уверенно чувствовали себя при работе с этим современным стеком.

Установка Nuxt.js с поддержкой Vue 3

Первый шаг — установка проекта

Сейчас Nuxt 3 основан на Vue 3 "из коробки". Для начала скачайте и установите Node.js (желательна версия не ниже 16). После этого выполните в вашей консоли следующую команду:

npx nuxi init my-nuxt-app
cd my-nuxt-app
npm install

Здесь мы используем nuxi, который — официальный CLI для Nuxt 3. Давайте разберем, что происходит:

  • npx nuxi init my-nuxt-app — создает новую директорию с базовой структурой Nuxt 3 приложения.
  • npm install — устанавливает все зависимости, включая Vue 3, Nuxt 3 и необходимые плагины.

Теперь запустите приложение:

npm run dev

После этого вы сможете открыть браузер и увидеть страницу приветствия Nuxt.

Структура проекта

Рассмотрим основные директории:

  • pages/ — именно здесь вы создаете .vue файлы, которые автоматически становятся маршрутами приложения.
  • components/ — здесь лежат компоненты, которые вы выносите для повторного использования.
  • layouts/ — шаблоны для страниц, например, с разной шапкой/футером.
  • plugins/ — файлы для инициализации сторонних библиотек или собственного кода перед загрузкой приложения.
  • middleware/ — функции, выполняющиеся между запросом пользователя и отображением страницы (авторизация, редиректы и т.д.).
  • nuxt.config.ts — основной конфиг Nuxt 3.

Вот так это может выглядеть:

my-nuxt-app/
|-- pages/
|-- components/
|-- layouts/
|-- plugins/
|-- middleware/
|-- nuxt.config.ts

Принципы работы SSR в Nuxt.js

Зачем нужен SSR

SSR, или Server-Side Rendering, позволяет рендерить ваш сайт на сервере, а не только в браузере. Это критически важно для:

  • Улучшения SEO (поисковики видят готовый HTML-код)
  • Повышения скорости первого отображения страницы (First Contentful Paint)
  • Возможности предзагрузки данных до отправки страницы пользователю

В Nuxt 3 все эти процессы абстрагированы и удобны в использовании.

Universal приложения и статическая генерация

Nuxt поддерживает два главных режима:

  • SSR (Universal Mode): Сервер генерирует HTML-код для каждого запроса
  • SSG (Static Site Generation): Весь контент генерируется заранее на этапе билда, и сайт работает как статический

Ваша конфигурация зависит только от nuxt.config.ts. Например:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true // для SSR-приложений (это дефолт)
})

А если хотите статическую генерацию:

export default defineNuxtConfig({
  ssr: true,
  nitro: {
    preset: 'static'
  }
})

Маршрутизация страниц

Автоматическая маршрутизация

Nuxt самостоятельно создает маршруты для каждого .vue файла в папке pages. Смотрите, я покажу на примере:

pages/
  index.vue        // корневая страница (/)
  about.vue        // страница /about
  blog/
    index.vue      // страница /blog
    [slug].vue     // страница /blog/:slug (динамический маршрут)

Вам не нужно руками настраивать роутер – всё работает автоматически.

Пример динамического маршрута

Создайте файл pages/blog/[slug].vue. Nuxt сам поймет, что slug — параметр маршрута.

<template>
  <div>
    <h1>Блог: {{ slug }}</h1>
  </div>
</template>

<script setup>
const route = useRoute() // Получаем объект маршрута
const slug = route.params.slug // Достаем параметр динамического маршрута
</script>

Обратите внимание, как просто управлять динамическими маршрутами — лишь имя файла имеет значение.

Работа с данными и асинхронный рендеринг

Использование useAsyncData и useFetch

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

Это ключевой момент для SSR-приложений, ведь данные нужно загрузить до того, как страница срендерится и отдастся пользователю. Смотрите пример:

<template>
  <div>
    <h1>Пост: {{ post.title }}</h1>
    <p>{{ post.body }}</p>
  </div>
</template>

<script setup>
// Загружаем данные поста по id
const { data: post, pending, error } = await useAsyncData('post', async () => {
  const id = useRoute().params.id // Берем id из маршрута
  const res = await $fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
  return res
})
</script>
  • useAsyncData инициирует загрузку данных, доступных для SSR.
  • await гарантирует, что данные подгрузятся до рендера страницы.
  • pending и error помогают обрабатывать состояние загрузки.

Альтернатива — useFetch

<script setup>
// То же самое, только чуть проще
const { data: post } = await useFetch(`https://jsonplaceholder.typicode.com/posts/${useRoute().params.id}`)
</script>

Используйте useFetch, когда необходимо сделать простой запрос.

Вывод ошибок и загрузки

Добавьте чтение ошибок, чтобы пользователь не видел пустой страницы, если API временно недоступно:

<template>
  <div v-if="pending">Загрузка...</div>
  <div v-else-if="error">Ошибка: {{ error.message }}</div>
  <div v-else>
    <h1>{{ post.title }}</h1>
    <p>{{ post.body }}</p>
  </div>
</template>

Layouts и композиция страниц

Использование кастомных layout'ов

Папка layouts/ помогает задавать различные шаблоны для страниц. Например, сделайте файл layouts/admin.vue:

<template>
  <div>
    <header>Панель администратора</header>
    <slot /> <!-- Здесь будет содержимое страницы -->
    <footer>Административный футер</footer>
  </div>
</template>

На странице вы указываете нужный layout через definePageMeta:

<script setup>
definePageMeta({
  layout: 'admin'
})
</script>

Теперь страница будет отображаться с вашим шаблоном.

Работа с middleware (промежуточные обработчики)

Middleware позволяют выполнять код до рендера страницы. Например, можно реализовать защиту страниц авторизацией.

Создайте файл middleware/auth.global.ts:

export default defineNuxtRouteMiddleware((to, from) => {
  const isLoggedIn = useAuth().isLoggedIn // Допустим, есть хук авторизации
  if (!isLoggedIn && to.path.startsWith('/admin')) {
    return navigateTo('/login') // Если не авторизован, отправить на логин
  }
})
  • Такой middleware будет исполняться на каждом запросе.
  • Если надо только для одной страницы — используйте нен глобальный middleware.

Плагины и расширения

Создание plugin'ов

Папка plugins/ позволяет подключать сторонние библиотеки и модули до запуска приложения. Например, интеграция с библиотекой UI:

plugins/element-plus.ts:

import ElementPlus from 'element-plus'
import { defineNuxtPlugin } from '#app'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(ElementPlus)
})

Импорт глобальных функций или переменных

Аналогично можно добавить глобальные фильтры, миксины или собственные утилиты.

Интеграция с внешними API и серверная логика

Nuxt 3 оснащен фреймворком Nitro для серверной логики и маршрутов API.

Пример серверного обработчика

Добавьте файл server/api/hello.ts:

export default defineEventHandler((event) => {
  // Здесь может быть доступ к базе данных и т.д.
  return { message: 'Привет с сервера!' }
})

Теперь по адресу /api/hello доступен этот API-роут.

Вызов сервера из клиента

В компоненте:

<script setup>
const { data } = await useFetch('/api/hello')
// data.value.message теперь хранит 'Привет с сервера!'
</script>

Очень удобно для интеграции с собственной backend-логикой или внешними сервисами.

Хуки жизненного цикла и Composition API

Nuxt 3 поддерживает стандартные Vue 3 хуки и Composition API.

Например:

<script setup>
onMounted(() => {
  // Этот код выполнится, когда компонент смонтирован на клиенте
  console.log('Компонент готов!')
})
</script>

Можно свободно использовать:

  • ref, reactive, computed из Vue 3
  • watch, watchEffect
  • provide/inject для зависимостей компонент

SEO и мета-теги

Для серверно-рендеренных приложений SEO критично важен. В Nuxt 3 это реализовано очень просто:

<script setup>
useHead({
  title: 'Моя страница',
  meta: [
    { name: 'description', content: 'Описание страницы для поисковиков' }
  ]
})
</script>

Заголовки, описания, ключи передаются в head страницы во время SSR и видны поисковым роботам.

Работа с TypeScript

Nuxt 3 написан на TypeScript, и вы можете сразу использовать .ts файлы, типизацию компонентов и серверных роутов.

Вам доступны типы для маршрутов, данных, конфигов — это сильно повышает надежность и удобство разработки.

// nuxt.config.ts поддерживает типизацию автоматически

Деплой SSR-приложения

Для деплоя SSR-приложения подойдет любой сервер Node.js или облачные платформы (Vercel, Netlify, Render). Для развертывания:

  1. Выполните сборку:
npm run build
  1. Запустите сервер:
npm run start

Если используется статическая генерация:

npm run generate

Все страницы появятся в директории /dist и будут готовы для хостинга на любом CDN или S3.

Заключение

Nuxt.js в связке с Vue 3 — это современный инструмент, который раскрывает все преимущества SSR и SSG без лишних хлопот. Вы можете быстро создать и масштабируемый сайт, и мощную SPA-платформу с удобной архитектурой, поддержкой TypeScript, SSR, автоматической маршрутизацией и огромным количеством модулей для интеграции с внешними сервисами.

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

Частозадаваемые технические вопросы по теме Nuxt.js и Vue 3

Как передать параметры между страницами и получать их в Nuxt 3?

В Nuxt 3 параметры маршрута автоматически доступны через useRoute(). Например, для страницы /user/[id].vue используйте:

<script setup>
const id = useRoute().params.id
</script>

Если нужно передать query-параметры (например, /profile?tab=posts), используйте useRoute().query.tab.

Как реализовать защищенные маршруты, чтобы некоторые страницы открывались только авторизованным пользователям?

Добавьте middleware и проверьте стейт пользователя.

middleware/auth.ts: ts export default defineNuxtRouteMiddleware((to) => { const user = useAuth().user if (!user) return navigateTo('/login') }) На странице используйте: vue <script setup> definePageMeta({ middleware: 'auth' }) </script>

Как настроить кастомный серверный рендеринг, если нужно использовать сторонний сервер (например, Express)?

Используйте Nuxt 3 как middleware:

import { loadNuxt } from 'nuxt/app'
const nuxt = await loadNuxt({ for: 'start' })
// Оборачивайте сервер Express
app.use(nuxt.render)

Подробнее в официальной документации.

Как правильно подключать сторонние CSS-фреймворки или preprocessor (Sass, Less) в Nuxt 3?

Добавьте нужный пакет (npm install sass), а потом импортируйте свой файл в секцию css конфига:

export default defineNuxtConfig({
  css: ['~/assets/styles/main.scss']
})

Как оптимизировать производительность SSR Nuxt проекта?

  • Используйте динамический импорт компонентов (defineAsyncComponent)
  • Включайте кэширование запросов
  • Минимизируйте количество глобальных middleware
  • Используйте picture/source для изображений и CDN для статики

Эти шаги повысят скорость и удобство масштабирования вашего SSR приложения.

Стрелочка влевоКак организовать страницы и маршруты в проекте на VueСоздание серверных приложений на Vue с помощью Nuxt jsСтрелочка вправо

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Открыть базу знаний