Олег Марков
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). Для развертывания:
- Выполните сборку:
npm run build
- Запустите сервер:
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 приложения.