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

Создание серверных приложений на Vue с помощью Nuxt js

Автор

Олег Марков

Введение

Создание современных веб-приложений требует не только красивого интерфейса, но и высокой производительности, SEO-оптимизации и безопасности. При разработке сложных SPA (Single Page Application) на Vue многие сталкиваются с трудностью реализации серверной логики, эффективной маршрутизации и предварительной загрузки данных для SEO. Nuxt.js — это фреймворк, который расширяет возможности Vue, позволяя строить полноценные серверные приложения, в том числе сочетающие SSR (Server Side Rendering) и статическую генерацию. Здесь вы узнаете, как начать создавать серверные приложения на Vue с помощью Nuxt.js, в чем его преимущества и какие ключевые возможности он предлагает для реальных задач.

Что такое Nuxt.js

Nuxt.js — прогрессивный фреймворк на базе Vue.js, предназначенный для создания универсальных приложений. Основная задача Nuxt — автоматизировать и упростить организацию работы с:

  • SSR (рендеринг на сервере)
  • статической генерацией страниц
  • маршрутизацией и структурой директорий
  • предварительной загрузкой данных
  • интеграцией API на сервере

Nuxt подходит как для проектов, где нужен SEO (например, блоги, маркетплейсы, корпоративные сайты), так и для динамических веб-приложений с богатой клиентской логикой.

В основе Nuxt лежит концепция “конфигурируй по желанию, работай из коробки”, что помогает быстро стартовать с минимальными настройками, расширяя проект по мере роста требований.

Отличие Nuxt.js от Vue

Если вы уже работали с Vue, возможно, делали SPA с vue-cli или vite. Но сразу при масштабировании приложения возникали задачи:

  • автоматическое разделение кода (code splitting)
  • мощная маршрутизация
  • SEO-оптимизация
  • универсальность эндпойнтов для API

Во Vue эти элементы реализуются вручную, что усложняет поддержку. Nuxt.js берет на себя эти задачи:

  • Автоматически создает роуты на основе файловой структуры
  • Инкапсулирует логику SSR — не нужно вручную настраивать сервер
  • Предоставляет API-роуты через serverMiddleware или Nitro (в Nuxt 3+)
  • Позволяет легко интегрировать middlewares, плагины и модули

Давайте посмотрим, как это реализовано на практике.

Структура серверного приложения на Nuxt.js

В Nuxt основная работа строится вокруг отдельных директорий:

  • pages/ — любые .vue-файлы автоматически становятся роутами
  • components/ — переиспользуемые компоненты (не роуты)
  • server/ — функции и API эндпойнты в Nuxt 3+ (подробнее ниже)
  • plugins/ — подключаемые плагины
  • middleware/ — промежуточная логика

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

my-app/
  pages/
    index.vue
    about.vue
    users/
      _id.vue
  components/
    Navbar.vue
  server/
    api/
      hello.js
  nuxt.config.ts
  package.json

Теперь давайте поймем, как включается рендеринг на сервере и создаются серверные эндпойнты.

Рендеринг на стороне сервера (SSR) в Nuxt.js

SSR означает, что HTML-страницы обрабатываются и генерируются на сервере, а не на клиенте (в браузере), что помогает:

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

Nuxt поддерживает разные режимы работы:

  1. SSR (default)
    “Universal” — сервер генерирует готовый HTML, дальше клиент берет управление (гидратация).

  2. Single Page Application (SPA)
    Весь рендеринг выполняется на клиенте, сервер только отдает статические файлы.

  3. Статическая генерация (SSG)
    На этапе сборки формируются статические HTML-страницы для каждого маршрута.

Чтобы включить/выключить SSR, укажите флаг в nuxt.config.ts:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true, // для SSR или false для SPA
})

Большинство возможностей по универсальной отрисовке реализованы “под капотом” — вы просто пишете страницы и компоненты, а Nuxt сам заботится о рендеринге там, где это требуется.

Создание серверных API с помощью Nuxt.js

В современных Nuxt (3+) появилась директория server/, в которой можно размещать собственные API эндпойнты на Node.js. Это позволяет держать клиентский и серверный код рядом, не разносить проекты, и быстро обмениваться данными без внешнего бэкенда.

Добавление API эндпойнта

Смотрите, как можно создать API-эндпойнт:

// server/api/hello.js

export default defineEventHandler(async (event) => {
  // Получаем клиентский IP, как пример серверной логики
  const ip = event.node.req.socket.remoteAddress
  return { message: `Hello from server! Your IP is ${ip}` }
})
  • Любой файл в server/api/ становится эндпойнтом по соответствующему маршруту: этот файл — /api/hello
  • Вы можете обрабатывать методы запроса, заголовки, получать тело запроса через утилиты Nuxt

Теперь вы можете выполнить запрос с клиента:

// В компоненте/странице
const { data } = await useFetch('/api/hello')

Этот подход делает развитие серверной логики очень удобным. Не требуется настраивать отдельный бэкенд: вы пишете серверные функции там же, где клиентскую логику.

Асинхронная загрузка данных в компонентах

Nuxt встраивает удобные хелперы для получения серверных данных до рендера компонента. Попробуйте следующее:

<template>
  <div>
    <p>{{ data.message }}</p>
  </div>
</template>

<script setup>
const { data, pending, error } = await useFetch('/api/hello')
</script>
  • Функция useFetch автоматически выполняет серверный запрос при SSR, на клиенте — после гидратации.
  • Полученные данные становятся доступными до первого рендера — это ускоряет загрузку.

Продвинутая серверная логика: middleware и обработка запросов

Часто нужно проверять авторизацию, логгировать действия или изменять объекты запроса до передачи в конечный обработчик. Для этого Nuxt предлагает промежуточные серверные функции (server middleware).

Пример: проверка авторизации

Создадим middleware для серверных эндпойнтов:

// server/middleware/auth.js

export default eventHandler(async (event) => {
  // Проверяем наличие cookie 'token'
  const token = getCookie(event, 'token')
  if (!token) {
    throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
  }
})

Чтобы применить middleware к определенному API-роуту:

// server/api/protected.js

import auth from '../middleware/auth.js'

export default defineEventHandler(async (event) => {
  await auth(event) // защита маршрута
  // Основная логика эндпойнта ниже
  return { message: 'Вы авторизованы' }
})

Здесь вы видите, как просто подключать промежуточную логику для отдельных эндпойнтов.

Работа с внешними базами данных

Любой эндпойнт в server/api/ — это полноценная серверная функция, где допустим импорт Node.js модулей, любых библиотек для работы с БД (например, Prisma, Sequelize, mongoose, pg, mysql2 и т.д.).

Пример с MongoDB:

// server/api/users.js

import { MongoClient } from 'mongodb'

const client = new MongoClient('mongodb://localhost:27017')
const dbName = 'mydb'

export default defineEventHandler(async (event) => {
  await client.connect()
  const db = client.db(dbName)
  const users = await db.collection('users').find().toArray()
  return users
})
  • Здесь реализован API-эндпойнт /api/users, который возвращает список пользователей из MongoDB.
  • Вы можете обрабатывать любые методы (GET/POST/PUT/DELETE), парсить тело, работать с куками и сессиями.

Динамические маршруты и параметры

В директории pages/ структура файлов определяет ваши пользовательские маршруты.

Например:

pages/
  users/
    _id.vue

Это создаст маршрут /users/:id. Внутри компонента получите параметр так:

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

Можно асинхронно загружать данные пользователя по его id:

<script setup>
const route = useRoute()
const { data } = await useFetch(`/api/users/${route.params.id}`)
</script>

При SSR эти данные также будут загружены до рендера страницы.

Интеграция клиентских и серверных библиотек

Nuxt поддерживает подключение сторонних npm-библиотек — как для клиента, так и для сервера. Если библиотека использует Node API, импортируйте её в серверных файлах или эндпойнтах, а не в браузерном коде.

Например, работа с JWT на сервере:

// server/api/login.js

import jwt from 'jsonwebtoken'

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  // Проверка логина/пароля...
  const token = jwt.sign({ userId: body.userId }, 'секретка')
  setCookie(event, 'token', token)
  return { ok: true }
})

Деплой и запуск серверного Nuxt-приложения

Nuxt можно запускать:

  • В Dev-режиме (разработка): nuxi dev
  • В production-сборке:
    1. Сборка проекта: nuxi build
    2. Запуск: nuxi preview или (используя Node.js сервер) node .output/server/index.mjs

Можно развернуть приложение где угодно: на Vercel, Netlify, Heroku, собственном VPS, в Docker-контейнере. Nuxt поддерживает auto adapter'ы для популярных платформ.

Лучшая практика — разделение логики и отказоустойчивость

Работая с серверным кодом, старайтесь:

  • Разделять клиентскую и серверную логику (не импортируйте Node-модули в компоненты, которые исполняются в браузере)
  • Обрабатывать все нестандартные случаи (ошибки при запросах к БД, отсутствие данных, невалидные куки)
  • Использовать environment переменные для секретов (например, через .env)
  • Структурировать большие проекты с помощью модулей или слоёв

Предварительная загрузка данных (pre-fetching)

Nuxt позволяет предварительно загружать любые данные как для сервера, так и для клиента. Для этого используйте useAsyncData или useFetch внутри компонента или страницы.

<script setup>
const { data, pending, error } = await useAsyncData('key', () => $fetch('/api/data'))
</script>
  • Всё, что возвращает сервер, автоматически сериализуется для передачи между сервером и клиентом
  • Это упрощает построение динамических, но быстро загружаемых страниц

Заключение

Nuxt.js — это мощный фреймворк, делающий разработку серверных приложений на Vue гораздо проще и быстрее. Здесь вы получили обзор основных механизмов Nuxt: автоматическая организация роутинга, легкая интеграция серверной логики, рендеринг на сервере и работа с асинхронными данными. С его помощью вы сможете строить как оптимизированные для поисковиков сайты, так и полноценные full-stack решения, не разделяя проекты на клиентский и серверный. Nuxt отлично подходит для проектов любого масштаба благодаря модульной архитектуре и большому количеству готовых плагинов.

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

Как подключить внешние API или собственный сервер?

Если вам нужно проксировать запросы к внешнему API — используйте серверные эндпойнты Nuxt в server/api/ и в них делайте HTTP-запросы с помощью fetch или сторонних библиотек вроде axios. Для сложных сценариев можно использовать proxy-модули, либо разворачивать отдельный Serve Middleware.

Можно ли использовать WebSockets в серверной части Nuxt?

Да, но только вне стандартных API-эндпойнтов. Для работы с WebSockets интегрируйте свой сервер (например, на ws), используя серверные хуки Nuxt или запуск через serverMiddleware. Внимательно разграничивайте зоны работы SSR и своего исходного WebSocket-сервера.

Как управлять сессиями и куками?

Для работы с куками используйте функции getCookie и setCookie (доступны из пакета h3, который используется внутри Nuxt server). Для полноценной работы сессий можно подключить сторонние пакеты (например, iron-session). Все манипуляции сессиями и куки лучше делать в файлов server/api/ или server/middleware/.

Как решать проблему "Cannot find module '...' " при импорте в серверный код?

Убедитесь, что устанавливаете серверные зависимости (npm install ...) и импортируете их строго в server-файлах. Импорт серверных пакетов в клиентские компоненты приведет к ошибке в браузере.

Где задавать переменные окружения?

Nuxt автоматически подхватывает переменные из .env, либо из системных переменных. Используйте внутри серверного кода — через process.env.NAME. Для передачи переменных на клиент используйте префикс NUXT_ в название переменной, тогда она будет доступна глобально (например, NUXT_API_URL).

Стрелочка влевоNuxt JS и Vue 3 для SSR приложенийИспользование Vue Native для разработки мобильных приложенийСтрелочка вправо

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

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

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

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

Все гайды по 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
Управление переменными и реактивными свойствами во 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
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование Vue Pro и его преимущества для профессиональной разработкиИспользование ref для управления ссылками и реактивностью в Vue 3Руководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

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

изображение курса

Vue 3 и Pinia

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

TypeScript с нуля

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

Next.js - с нуля

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

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