Перейти к содержимому

2. Установка и структура

Создание нового Nuxt 3 проекта — одна команда. Но понимание структуры файлов — это то, что превращает тебя из пользователя в мастера фреймворка. Давай разберём всё по косточкам.


Окно терминала
npx nuxi@latest init my-nuxt-app
# Или с конкретным шаблоном
npx nuxi@latest init my-nuxt-app --template github:nuxt/starter#v3
# Интерактивный режим (выбор опций)
npx nuxi@latest init

После выполнения команды Nuxi спросит:

  1. Package manager — npm, yarn, pnpm или bun
  2. Initialize git repository — создать .git
Окно терминала
cd my-nuxt-app
npm install
npm run dev

Открываем http://localhost:3000 — готово! 🎉


Окно терминала
# Dev сервер
npx nuxi dev
# Сборка для production
npx nuxi build
# Статическая генерация (SSG)
npx nuxi generate
# Preview production сборки
npx nuxi preview
# Добавить модуль
npx nuxi module add @nuxtjs/tailwindcss
# Добавить компонент/страницу/composable
npx nuxi add component MyButton
npx nuxi add page about
npx nuxi add composable useCounter
npx nuxi add layout admin
# Обновить Nuxt
npx nuxi upgrade
# Проверить проект
npx nuxi info
# Очистить кэш
npx nuxi cleanup

my-nuxt-app/
├── 📁 .nuxt/ ← АВТО: типы, временные файлы
│ ├── imports.d.ts ← Типы для авто-импортов
│ ├── components.d.ts ← Типы для компонентов
│ └── nuxt.d.ts ← Типы Nuxt
├── 📁 .output/ ← АВТО: production сборка
├── 📁 assets/ ← Ресурсы (обрабатывает Vite)
│ ├── css/
│ │ └── main.css ← Глобальные стили
│ ├── fonts/
│ └── images/
│ └── logo.svg
├── 📁 components/ ← Vue компоненты (авто-импорт)
│ ├── AppHeader.vue → <AppHeader>
│ ├── AppFooter.vue → <AppFooter>
│ ├── ui/
│ │ ├── Button.vue → <UiButton>
│ │ └── Card.vue → <UiCard>
│ └── global/ ← Глобальные компоненты
│ └── Icon.vue → <Icon> (доступен везде)
├── 📁 composables/ ← Vue composables (авто-импорт)
│ ├── useAuth.ts → useAuth()
│ ├── useCart.ts → useCart()
│ └── utils/
│ └── useFormat.ts → useFormat()
├── 📁 content/ ← @nuxt/content файлы
│ ├── index.md
│ └── blog/
│ └── first-post.md
├── 📁 layouts/ ← Шаблоны страниц
│ ├── default.vue ← Дефолтный layout
│ ├── admin.vue ← Кастомный layout
│ └── auth.vue ← Layout для авторизации
├── 📁 middleware/ ← Route middleware
│ ├── auth.ts → named middleware 'auth'
│ └── analytics.global.ts → глобальный middleware
├── 📁 pages/ ← Страницы (файловый роутинг)
│ ├── index.vue → /
│ ├── about.vue → /about
│ ├── blog/
│ │ ├── index.vue → /blog
│ │ └── [slug].vue → /blog/:slug
│ └── users/
│ ├── index.vue → /users
│ └── [id]/
│ ├── index.vue → /users/:id
│ └── edit.vue → /users/:id/edit
├── 📁 plugins/ ← Nuxt плагины
│ ├── analytics.client.ts ← Только клиент
│ ├── dayjs.ts ← Клиент + сервер
│ └── error-handler.server.ts ← Только сервер
├── 📁 public/ ← Статические файлы (без обработки)
│ ├── favicon.ico
│ ├── robots.txt
│ └── og-image.png
├── 📁 server/ ← Nitro сервер
│ ├── api/ ← API маршруты
│ │ ├── users.get.ts → GET /api/users
│ │ ├── users.post.ts → POST /api/users
│ │ └── users/
│ │ └── [id].get.ts → GET /api/users/:id
│ ├── routes/ ← Нестандартные маршруты
│ │ └── sitemap.xml.ts → /sitemap.xml
│ ├── middleware/ ← Серверный middleware
│ │ └── logger.ts
│ ├── plugins/ ← Nitro плагины
│ │ └── database.ts
│ └── utils/ ← Серверные утилиты
│ └── db.ts
├── 📁 utils/ ← Клиентские утилиты (авто-импорт)
│ ├── formatDate.ts → formatDate()
│ └── validators.ts → validateEmail() и т.д.
├── 📄 app.vue ← Корневой компонент
├── 📄 app.config.ts ← Runtime app конфиг
├── 📄 error.vue ← Страница ошибок
├── 📄 nuxt.config.ts ← Конфигурация Nuxt
├── 📄 tsconfig.json ← TypeScript конфиг
├── 📄 .env ← Переменные окружения
├── 📄 .nuxtignore ← Файлы для игнорирования
└── 📄 package.json

app.vue
<template>
<!-- NuxtLayout и NuxtPage — ключевые компоненты -->
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>

Или без layouts:

app.vue
<template>
<!-- Просто роутер без layouts -->
<NuxtPage />
</template>

Или полностью кастомный:

app.vue
<template>
<div>
<AppHeader />
<main>
<NuxtPage />
</main>
<AppFooter />
</div>
</template>

nuxt.config.ts
export default defineNuxtConfig({
// Совместимость с версией Nuxt
compatibilityDate: '2024-04-03',
// DevTools (только в разработке)
devtools: { enabled: true },
// SSR включён по умолчанию
ssr: true,
// Мета-информация приложения
app: {
head: {
title: 'My Nuxt App',
titleTemplate: '%s | My App',
htmlAttrs: { lang: 'ru' },
meta: [
{ name: 'description', content: 'Описание сайта' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Переходы между страницами
pageTransition: { name: 'page', mode: 'out-in' },
layoutTransition: { name: 'layout', mode: 'out-in' },
},
// CSS файлы
css: ['~/assets/css/main.css'],
// Глобальные компоненты/composables
components: {
dirs: [
'~/components',
{ path: '~/components/global', global: true }
]
},
// Настройка авто-импортов
imports: {
dirs: ['stores', 'utils/**'],
},
// Модули
modules: [
'@nuxtjs/tailwindcss',
'@pinia/nuxt',
'@nuxt/image',
'@nuxtjs/i18n',
],
// Runtime конфигурация
runtimeConfig: {
// Только серверная
jwtSecret: process.env.JWT_SECRET,
dbUrl: process.env.DATABASE_URL,
// Публичная (клиент + сервер)
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api',
siteName: 'My Nuxt App',
}
},
// Правила роутинга
routeRules: {
'/': { prerender: true },
'/blog/**': { isr: 3600 },
'/admin/**': { ssr: false, robots: false },
},
// Nitro конфигурация
nitro: {
// Предрендеринг
prerender: {
routes: ['/sitemap.xml', '/robots.txt'],
},
// Storage (KV хранилище)
storage: {
redis: { driver: 'redis', url: process.env.REDIS_URL }
}
},
// Vite конфигурация
vite: {
plugins: [],
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "~/assets/scss/variables";'
}
}
}
},
// TypeScript настройки
typescript: {
strict: true,
typeCheck: true,
},
// Экспериментальные фичи
experimental: {
viewTransition: true,
typedPages: true,
}
})

.env
DATABASE_URL=postgresql://user:pass@localhost/mydb
JWT_SECRET=super-secret-key-123
NUXT_PUBLIC_API_BASE=https://api.myapp.com
NUXT_PUBLIC_APP_NAME=My Super App

Важные правила:

NUXT_PUBLIC_* → попадает в public runtimeConfig
NUXT_* → попадает в private runtimeConfig
Остальные → доступны только через process.env на сервере

Окно терминала
# .nuxtignore — синтаксис как у .gitignore
# Игнорировать страницы
pages/old-page.vue
pages/experiments/**
# Игнорировать компоненты
components/deprecated/**
# Игнорировать test файлы в pages
**/*.test.vue
**/*.spec.vue

// app.config.ts — конфиг доступный на клиенте
// В отличие от runtimeConfig — не из ENV, а из кода
export default defineAppConfig({
theme: {
primaryColor: '#00dc82',
name: 'Nuxt Green',
},
ui: {
button: {
defaultVariants: {
color: 'primary',
size: 'md',
}
}
}
})
<script setup>
// Доступ везде
const appConfig = useAppConfig()
console.log(appConfig.theme.primaryColor) // '#00dc82'
</script>

Nuxt автоматически создаёт удобные псевдонимы:

// В любом файле можно использовать:
import MyUtil from '~/utils/myUtil' // ~ = корень проекта
import Component from '@/components/X' // @ = корень проекта
import type from '#imports' // # = .nuxt/
// В CSS:
background: url('~/assets/images/bg.jpg');