Структура проекта, файловый роутинг, layouts, авто-импорты, режимы рендеринга SSR/SPA/SSG и Nuxt DevTools
Nuxt 3 — это метафреймворк поверх Vue 3, который добавляет серверный рендеринг, файловый роутинг, авто-импорты и многое другое из коробки. Nuxt позволяет создавать production-ready приложения с минимальной конфигурацией.
Обычное Vue-приложение (SPA — Single Page Application) работает так: браузер загружает пустой HTML, потом JavaScript, который рендерит интерфейс. У этого подхода есть проблемы: медленная начальная загрузка, плохой SEO (поисковики видят пустую страницу), нет рендеринга на сервере.
Nuxt решает эти проблемы и добавляет множество удобств из коробки:
pages/ автоматически становится роутингом, не нужно настраивать Vue RouterСоздание нового Nuxt 3 проекта с помощью официального инструмента:
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run devКоманда nuxi init создаёт минимальный проект. Для проекта с дополнительными возможностями используйте шаблоны или добавляйте модули позже.
Nuxt использует соглашения по именованию директорий. Это важно понять — структура папок определяет поведение:
my-nuxt-app/
├── pages/ # Страницы → автоматический роутинг
│ ├── index.vue # → /
│ ├── about.vue # → /about
│ └── users/
│ ├── index.vue # → /users
│ └── [id].vue # → /users/:id (динамический сегмент)
├── components/ # Компоненты → авто-импорт
│ ├── AppHeader.vue
│ └── ui/
│ └── Button.vue # Доступен как <UiButton>
├── composables/ # Composables → авто-импорт
│ └── useAuth.ts
├── layouts/ # Лейауты страниц
│ ├── default.vue # Лейаут по умолчанию
│ └── admin.vue # Кастомный лейаут
├── middleware/ # Route middleware
│ └── auth.ts
├── plugins/ # Плагины Vue
│ └── myPlugin.ts
├── server/ # Server-side код
│ ├── api/ # API endpoints
│ │ └── hello.ts # → GET /api/hello
│ └── middleware/ # Server middleware
├── public/ # Статические файлы (без обработки)
│ └── favicon.ico
├── assets/ # Обрабатываемые ассеты (CSS, изображения)
│ └── css/
│ └── main.css
├── app.vue # Корневой компонент
├── nuxt.config.ts # Конфигурация Nuxt
└── package.json
Это корневой компонент всего приложения. По умолчанию в нём должен быть <NuxtPage> (аналог <RouterView>) и/или <NuxtLayout>:
<!-- app.vue -->
<template>
<!-- NuxtLayout + NuxtPage — стандартный паттерн -->
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>Можно добавить глобальные элементы: хедер, футер, уведомления:
<!-- app.vue с глобальными элементами -->
<template>
<div>
<AppHeader />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
<AppFooter />
<!-- Глобальный toast/notification -->
<Toast />
</div>
</template>Nuxt автоматически создаёт маршруты на основе структуры папки pages/. Это главное отличие от обычного Vue-приложения — не нужно настраивать Vue Router вручную:
pages/
├── index.vue → /
├── about.vue → /about
├── contact.vue → /contact
├── users/
│ ├── index.vue → /users
│ └── [id].vue → /users/:id
├── blog/
│ ├── index.vue → /blog
│ └── [slug].vue → /blog/:slug
└── [...slug].vue → /* (catch-all)
Создадим несколько страниц:
<!-- pages/index.vue -->
<template>
<div>
<h1>Добро пожаловать!</h1>
<NuxtLink to="/about">О нас</NuxtLink>
</div>
</template><!-- pages/users/[id].vue -->
<template>
<div>
<h1>Пользователь {{ userId }}</h1>
<p v-if="user">{{ user.name }}</p>
</div>
</template>
<script setup>
// В Nuxt useRoute() работает так же как в Vue Router
const route = useRoute()
const userId = computed(() => route.params.id)
// useFetch — основной способ загрузки данных в Nuxt (разберём в следующей теме)
const { data: user } = await useFetch(`/api/users/${userId.value}`)
</script>Специальные файлы:
[id].vue — динамический сегмент, route.params.id[[id]].vue — опциональный динамический сегмент[...slug].vue — catch-all маршрут, все сегменты путиЛейауты — это компоненты-обёртки для страниц. layouts/default.vue применяется ко всем страницам автоматически:
<!-- layouts/default.vue -->
<template>
<div>
<header>
<nav>
<NuxtLink to="/">Главная</NuxtLink>
<NuxtLink to="/about">О нас</NuxtLink>
</nav>
</header>
<main>
<!-- Содержимое страницы вставляется здесь -->
<slot />
</main>
<footer>
<p>© 2026 My App</p>
</footer>
</div>
</template><!-- layouts/admin.vue — отдельный лейаут для admin -->
<template>
<div class="admin-layout">
<AdminSidebar />
<div class="admin-content">
<AdminHeader />
<slot />
</div>
</div>
</template>Переключение лейаута на конкретной странице через definePageMeta:
<!-- pages/admin/index.vue -->
<template>
<div>
<h1>Панель администратора</h1>
</div>
</template>
<script setup>
// definePageMeta — макрос для метаданных страницы
definePageMeta({
layout: 'admin' // Использует layouts/admin.vue
})
</script><!-- Страница совсем без лейаута -->
<script setup>
definePageMeta({
layout: false
})
</script>Динамическая смена лейаута из компонента:
<script setup>
const { setPageLayout } = useLayout()
// Меняем лейаут динамически
function switchToAdmin() {
setPageLayout('admin')
}
</script>Одна из главных особенностей Nuxt — авто-импорты. Не нужно явно импортировать компоненты, composables и большинство Vue API:
<!-- В обычном Vue пришлось бы писать: -->
<!-- import { ref, computed, watch } from 'vue' -->
<!-- import { useRoute } from 'vue-router' -->
<!-- import MyComponent from '@/components/MyComponent.vue' -->
<!-- В Nuxt всё это доступно автоматически: -->
<script setup>
// ref, computed, watch — авто-импортируются из Vue
const count = ref(0)
const doubled = computed(() => count.value * 2)
// Nuxt composables тоже авто-импортируются
const route = useRoute()
const router = useRouter()
const config = useRuntimeConfig()
// useFetch, useAsyncData — Nuxt composables
const { data } = await useFetch('/api/posts')
</script>
<template>
<!-- Компоненты из папки components/ авто-импортируются -->
<AppHeader />
<MyCard :title="'Заголовок'" />
<!-- Nuxt компоненты тоже доступны -->
<NuxtLink to="/">Главная</NuxtLink>
<NuxtImage src="/logo.png" />
</template>Ваши собственные composables в папке composables/ тоже авто-импортируются:
// composables/useAuth.ts
export function useAuth() {
const user = ref(null)
async function login(credentials) {
// ...
}
return { user, login }
}<script setup>
// Не нужно импортировать — доступно автоматически!
const { user, login } = useAuth()
</script>Авто-импорты работают для вложенных компонентов с особым именованием. Компонент components/ui/Button.vue станет доступен как <UiButton>.
В Nuxt эти composables работают так же как в Vue Router, но авто-импортируются:
<script setup>
// Текущий маршрут — параметры, query, hash
const route = useRoute()
// Доступны все свойства:
console.log(route.path) // /users/123
console.log(route.params.id) // '123'
console.log(route.query.tab) // 'profile'
console.log(route.fullPath) // /users/123?tab=profile#contacts
// Навигация
const router = useRouter()
function goToHome() {
router.push('/')
}
function goToUser(id) {
router.push({ name: 'users-id', params: { id } })
}
</script>Важная особенность Nuxt: имена маршрутов генерируются автоматически на основе пути файла. Файл pages/users/[id].vue создаёт маршрут с именем users-id. Файл pages/blog/[slug].vue создаёт blog-slug.
Nuxt поддерживает несколько режимов рендеринга, которые можно настроить глобально или для отдельных маршрутов:
Universal rendering (SSR по умолчанию) — первый запрос рендерится на сервере, затем Vue берёт управление на клиенте (гидратация):
// nuxt.config.ts
export default defineNuxtConfig({
ssr: true // По умолчанию
})SPA режим — полностью клиентский рендеринг, как обычный Vue:
export default defineNuxtConfig({
ssr: false
})Гибридный режим — разные маршруты рендерятся по-разному:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // Предрендеринг при сборке
'/blog/**': { swr: 3600 }, // Stale-while-revalidate, кэш 1 час
'/admin/**': { ssr: false }, // SPA для admin
'/api/**': { cors: true } // CORS для API маршрутов
}
})SSG (Static Site Generation) — генерация всех страниц при сборке:
npx nuxi generateЭта команда сгенерирует статические HTML файлы для всех страниц в папку .output/public. Можно раздавать с любого CDN.
Конфигурационный файл Nuxt — мощный инструмент для настройки всего приложения:
// nuxt.config.ts
export default defineNuxtConfig({
// Метаданные приложения
app: {
head: {
title: 'My Nuxt App',
meta: [
{ name: 'description', content: 'My Nuxt 3 application' }
],
link: [
{ rel: 'icon', href: '/favicon.ico' }
]
}
},
// CSS файлы подключаемые глобально
css: ['@/assets/css/main.css'],
// Модули Nuxt (разберём в теме про продвинутый Nuxt)
modules: [
'@pinia/nuxt',
'@nuxtjs/tailwindcss',
'@nuxt/image'
],
// Переменные окружения (разберём в теме про продвинутый Nuxt)
runtimeConfig: {
apiSecret: process.env.API_SECRET,
public: {
apiBase: process.env.API_BASE || 'https://api.example.com'
}
},
// Настройки TypeScript
typescript: {
strict: true
},
// Настройки Vite (сборщик под капотом)
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/scss/variables.scss";'
}
}
}
}
})Nuxt DevTools — встроенный инструмент разработки, доступный через кнопку в нижней части экрана в режиме разработки.
Возможности DevTools включают просмотр всех страниц и маршрутов с их метаданными, список авто-импортов и компонентов, состояние сторов Pinia, запросы useFetch/useAsyncData и их результаты, модули и плагины приложения, а также профилирование производительности.
DevTools включается автоматически в режиме разработки:
// nuxt.config.ts — явное включение/отключение
export default defineNuxtConfig({
devtools: { enabled: true }
})<NuxtLink> — Nuxt-замена <RouterLink>. Поддерживает те же возможности, но добавляет умную предзагрузку:
<template>
<nav>
<!-- Внутренняя навигация — как RouterLink -->
<NuxtLink to="/">Главная</NuxtLink>
<NuxtLink to="/about">О нас</NuxtLink>
<!-- С активным классом -->
<NuxtLink to="/blog" active-class="text-primary font-bold">
Блог
</NuxtLink>
<!-- Внешняя ссылка — работает как обычный <a> -->
<NuxtLink to="https://nuxt.com" external>
Документация
</NuxtLink>
<!-- Предзагрузка отключена -->
<NuxtLink to="/heavy-page" :prefetch="false">
Тяжёлая страница
</NuxtLink>
</nav>
</template>По умолчанию <NuxtLink> предзагружает связанные страницы когда ссылка попадает в зону видимости. Это значительно ускоряет навигацию.
Nuxt 3 предоставляет мощный набор инструментов из коробки: файловый роутинг устраняет необходимость настройки Vue Router, авто-импорты убирают шаблонный код импортов, лейауты упрощают организацию структуры страниц, а гибкие режимы рендеринга позволяют выбрать оптимальный подход для каждого сценария. В следующей теме разберём получение данных — одну из ключевых возможностей Nuxt.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.