🏭 createUseFetch и createUseAsyncData
Теперь можно создавать собственные экземпляры useFetch и useAsyncData с нужными опциями по умолчанию (#32300).
// Простые значения по умолчанию
export const useClientFetch = createUseFetch({
server: false,
})
// Динамические значения по умолчанию с полным контролем слияния
export const useApiFetch = createUseFetch((currentOptions) => {
const runtimeConfig = useRuntimeConfig()
return {
...currentOptions,
baseURL: currentOptions.baseURL ?? runtimeConfig.public.baseApiUrl,
}
})
Используйте их так же, как useFetch — с полной типизацией и теми же опциями:
<script setup lang="ts">
// baseURL из runtimeConfig подставляется автоматически
const { data: users } = await useApiFetch('/users')
</script>
При передаче обычного объекта опции использования переопределяют значения по умолчанию. При передаче функции вы полностью управляете слиянием опций — можно комбинировать перехватчики, заголовки и другие сложные настройки.
Внутри за это отвечает новый ad-hoc модуль Nuxt: он сканирует папку composables и регистрирует ваши экземпляры для инъекции по ключу, поэтому они работают с SSR так же, как useAsyncData и useFetch.
Для того же подхода с useAsyncData есть createUseAsyncData.
🗺️ Vue Router v5
Мы перешли на vue-router v5 (#34181): зависимость от unplugin-vue-router больше не нужна. Это первое мажорное обновление vue-router со времён Nuxt 3, с множеством улучшений внутри.
Для большинства приложений миграция прозрачна. Если вы подключали unplugin-vue-router отдельно, его можно убрать из зависимостей.
Дальше планируем вывести типизированные маршруты из экспериментального статуса. 👀
💪 Типизированные пропсы лейаутов в definePageMeta
Теперь пропсы лейаутам можно передавать прямо из definePageMeta (#34262). Лейауты можно параметризовать для каждой страницы без provide/inject и обходных решений. Подробности — в обновлённой документации.
definePageMeta({
layout: {
name: 'panel',
props: {
sidebar: true,
title: 'Dashboard',
},
},
})
Пропсы полностью типизированы (#34409): при определении пропсов в лейауте в definePageMeta доступны автодополнение и проверка типов.
<script setup lang="ts">
defineProps<{
sidebar?: boolean
title?: string
}>()
</script>
🗣️ Композабл useAnnouncer
Доступность усилена новым композаблом useAnnouncer и компонентом <NuxtAnnouncer> (#34318). useRouteAnnouncer объявляет смену страницы для скринридеров, а многим приложениям нужно объявлять динамические изменения на странице — отправку форм, состояния загрузки, результаты поиска и т.д.
<template>
<NuxtAnnouncer />
<NuxtRouteAnnouncer />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<script setup lang="ts">
const { polite, assertive } = useAnnouncer()
async function submitForm() {
try {
await $fetch('/api/contact', { method: 'POST', body: formData })
polite('Message sent successfully')
}
catch (error) {
assertive('Error: Failed to send message')
}
}
</script>
useAnnouncer особенно полезен, когда контент меняется динамически без смены фокуса.🚀 Переход на unrouting
Генерация file-system маршрутов Nuxt перенесена на unrouting (#34316) с использованием trie для построения маршрутов. Холодный старт примерно тот же (~8 мс против ~6 мс для больших приложений), зато изменения в dev-сервере до 28× быстрее, когда страницы не добавляются и не удаляются, и примерно на 15% быстрее в остальных случаях.
Генерация маршрутов стала более детерминированной и больше не зависит от порядка файлов страниц.
🍫 Умная работа с payload для кэшированных маршрутов
При рендере кэшированного маршрута (ISR/SWR) с извлечением payload браузер сразу запрашивает _payload.json вторым запросом — и это запускает полный повторный SSR той же страницы. В serverless это может поднять вторую lambda до завершения стриминга первого ответа.
В этом релизе это учтено двумя изменениями (#34410):
- Режим
payloadExtraction: 'client': полный payload встраивается в начальный HTML, при этом_payload.jsonпо-прежнему генерируется для клиентской навигации. - In-memory LRU кэш payload в рантайме, чтобы запросы
_payload.jsonобслуживались без полного повторного рендера.
export default defineNuxtConfig({
experimental: {
payloadExtraction: 'client',
},
})
payloadExtraction: 'client' станет значением по умолчанию при compatibilityVersion: 5. Кэш в рантайме действует для всех пользователей.🍪 Опция refresh для useCookie
При использовании cookies для сессий часто нужно продлевать срок жизни без смены значения. Новая опция refresh решает это (#33814):
const session = useCookie('session-id', {
maxAge: 60 * 60,
refresh: true,
})
// Продлевает срок при каждом обращении, даже при том же значении
session.value = session.value
♻️ Сброс useState к начальному значению
useState и clearNuxtState теперь поддерживают сброс к начальному значению вместо очистки в undefined (#33527). Поведение согласовано с useAsyncData и удобнее для управления состоянием.
const count = useState('counter', () => 0)
count.value = 42
// Сброс в 0 (начальное значение), а не в undefined
clearNuxtState('counter')
🕵️♂️ Улучшенная защита от импортов
По мотивам TanStack Start, защита от импортов теперь показывает подсказки и полный trace происхождения проблемного импорта (#34454). Так проще понять, почему server-only импорт оказался в клиентском бандле.
Например, при случайном импорте из server route в компоненте:

Trace показывает цепочку импортов (компонент импортирован со страницы), точную строку и конкретные рекомендации по исправлению.
Планируем и дальше улучшать сообщения об ошибках. 🪵
🔮 Типы view transitions
В экспериментальной поддержке view transitions Nuxt теперь можно задавать типы переходов (#31982). Так можно использовать разные переходы для разных сценариев навигации (вперёд/назад, вкладки и страницы и т.д.).
💡 Улучшенные подсказки по optimizeDeps
Когда Vite находит новые зависимости в рантайме и перезагружает страницы, Nuxt теперь показывает готовый фрагмент для nuxt.config.ts, чтобы предсобрать их (#34320). При старте также выводятся предупреждения о неразрешаемых записях.
🏷️ Нормализованные имена компонентов страниц (экспериментально)
Новая экспериментальная опция приводит имена компонентов страниц в соответствие с именами маршрутов (#33513) — удобнее в devtools и при отладке.
export default defineNuxtConfig({
experimental: {
normalizeComponentNames: true,
},
})
⚡ Профилирование сборки
Хотите понять, куда уходит время сборки? Теперь можно получить детальную разбивку по этапам сборки Nuxt (#34468, nuxt/cli#1243):
nuxt build --profile
В отчёте — длительность, изменение RSS и heap для каждой фазы сборки, модуля и плагина бандлера:

Профилируются и отдельные модули с плагинами бандлера, чтобы проще находить узкие места. Записываются три формата:
- Chrome Trace (
.nuxt/perf-trace.json) — открыть вchrome://tracingили Perfetto для временной шкалы - JSON-отчёт (
.nuxt/perf-report.json) — машинно-читаемые данные для анализа во времени - CPU-профиль (
nuxt-build.cpuprofile) — открыть в Chrome DevTools или VS Code для flame graph
Для ещё более детального вывода используйте --profile=verbose, чтобы печатать разбивку по времени в консоль.
Мы будем использовать эту возможность, чтобы делать Nuxt ещё быстрее — и если производительность вам важна, это хороший повод поучаствовать в разработке!
🔥 Улучшения производительности
- Парсинг ID модулей до ~14 000× быстрее — цепочка
new URL()+ regex заменена на одинindexOf+ slice (#34451) - Отключён prefetch по видимости NuxtLink в dev — Vite больше не обнаруживает и не перезагружает зависимости без необходимости (#34325)
⬆︎ Обновление
Рекомендуем выполнить:
npx nuxt upgrade --dedupe
Команда дедуплицирует lockfile и поможет подтянуть обновления зависимостей Nuxt, в том числе из экосистемы unjs.
👉 Full Release Notes
Спасибо всем, кто участвовал в этом релизе! 💚