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

25. Nuxt 4: новые возможности

Nuxt 4 — следующее поколение фреймворка с улучшенной структурой проекта, лучшей производительностью и упрощённой миграцией. Многие возможности уже доступны в Nuxt 3.x через экспериментальные флаги.


Главное изменение Nuxt 4 — введение директории app/ для хранения кода приложения:

my-nuxt3-app/
├── assets/
├── components/
├── composables/
├── layouts/
├── middleware/
├── pages/
├── plugins/
├── public/
├── server/
├── stores/
├── utils/
├── app.vue
├── error.vue
└── nuxt.config.ts
my-nuxt4-app/
├── app/ # ← ВСЁ приложение теперь здесь
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── layouts/
│ ├── middleware/
│ ├── pages/
│ ├── plugins/
│ ├── stores/
│ ├── utils/
│ ├── app.vue
│ └── error.vue
├── public/ # статика (остаётся в корне)
├── server/ # серверный код (остаётся в корне)
└── nuxt.config.ts # конфигурация (остаётся в корне)

Активируйте Nuxt 4 совместимость уже сейчас:

nuxt.config.ts
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
}
})

После этого Nuxt будет искать файлы сначала в app/, затем в корне проекта.


// Nuxt 3 — данные не обновляются при смене параметров маршрута
const { data } = await useAsyncData('user', () =>
fetchUser(route.params.id)
)
// Nuxt 4 — автоматическое отслеживание зависимостей
const { data } = await useAsyncData(() =>
fetchUser(route.params.id)
// ключ генерируется автоматически
// автоматически перезапускается при изменении route.params.id
)
// Данные теперь деится между страницами при prerender
// Один запрос к /api/config для всех 1000 страниц
const { data: config } = await useAsyncData('config', () =>
$fetch('/api/config'),
{ server: true }
)
// app/router.options.ts (раньше app/router.options.ts уже существовал)
import type { RouterConfig } from '@nuxt/schema'
export default <RouterConfig>{
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition
if (to.hash) return { el: to.hash, behavior: 'smooth' }
return { top: 0 }
}
}

🚀 Новые экспериментальные функции (Nuxt 3.x → 4)

Заголовок раздела «🚀 Новые экспериментальные функции (Nuxt 3.x → 4)»
nuxt.config.ts
export default defineNuxtConfig({
experimental: {
typedPages: true
}
})
// Типизированная навигация
const router = useRouter()
router.push({ name: 'blog-slug', params: { slug: 'my-post' } })
// TypeScript знает о структуре params!
export default defineNuxtConfig({
experimental: {
viewTransition: true
}
})
<template>
<!-- View Transitions API для плавной навигации -->
<NuxtLink :to="post.path" :view-transition-name="post.id">
{{ post.title }}
</NuxtLink>
</template>
// Оптимизированная загрузка внешних скриптов
export default defineNuxtConfig({
modules: ['@nuxt/scripts'],
scripts: {
registry: {
googleAnalytics: true,
fathomAnalytics: true,
stripe: true
}
}
})
<script setup>
const { $script } = useScriptGoogleAnalytics({
id: 'G-XXXXXXXXXX'
})
</script>

<!-- Nuxt 4: более гранулярный контроль -->
<script setup>
const { data, status } = await useAsyncData('data', fetchData)
// status: 'idle' | 'pending' | 'success' | 'error'
</script>
<template>
<div v-if="status === 'pending'">Загрузка...</div>
<div v-else-if="status === 'error'">Ошибка</div>
<div v-else>{{ data }}</div>
</template>
// Nuxt 4 автоматически удаляет неиспользуемые части
// Vue Router, Pinia и другие пакеты tree-shaken агрессивнее
export default defineNuxtConfig({
optimization: {
keyedComposables: true
}
})

// Nuxt 4 — улучшенный доступ к заголовкам
const xForwardedFor = useRequestHeader('x-forwarded-for')
const userAgent = useRequestHeader('user-agent')
// Установка заголовков ответа
const setHeader = useResponseHeader()
setHeader('X-Custom-Header', 'value')
// Nuxt 4 — расширенные SEO возможности
useSeoMeta({
title: 'Заголовок страницы',
ogTitle: 'Заголовок для OG',
description: 'Описание страницы',
ogDescription: 'OG описание',
ogImage: 'https://example.com/og.jpg',
twitterCard: 'summary_large_image',
twitterTitle: 'Twitter заголовок',
// Новые в v4:
articlePublishedTime: new Date().toISOString(),
articleAuthor: ['Александр']
})

Окно терминала
npx nuxi upgrade --force
nuxt.config.ts
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
}
})
Окно терминала
mkdir app
# Переместить файлы приложения
mv assets app/
mv components app/
mv composables app/
mv layouts app/
mv middleware app/
mv pages app/
mv plugins app/
mv stores app/
mv utils app/
mv app.vue app/
mv error.vue app/
// Было (Nuxt 3)
const { data } = await useAsyncData(
'user-' + userId,
() => fetchUser(userId)
)
// Стало (Nuxt 4 рекомендованный стиль)
const { data } = await useAsyncData(
() => fetchUser(userId)
// ключ генерируется автоматически из функции
)
// Убедитесь что алиасы работают
// ~ и @ теперь указывают на app/ директорию
import MyComponent from '~/components/MyComponent.vue'
// Nuxt автоматически резолвит к app/components/

АспектNuxt 3Nuxt 4
СтруктураФайлы в корнеФайлы в app/
useAsyncData ключОбязательныйАвтогенерация
View TransitionsЭкспериментальноСтабильно
Typed PagesЭкспериментальноСтабильно
Shared PrerenderНетЕсть
Scripts ModuleОтдельноВстроено
CompatibilitycompatibilityVersion: 4

По дорожной карте:

  • Nuxt 3.x — новые функции добавляются через future.* флаги
  • Nuxt 4 — стабильный релиз после завершения экспериментального периода
  • Миграция — максимально неломающая (breaking changes минимальны)
// Начинайте тестировать уже сейчас:
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
},
// Включить все Nuxt 4 поведения:
experimental: {
typedPages: true,
viewTransition: true,
payloadExtraction: true
}
})