# Nuxt 4 у 2026 році: Нова структура каталогів та міграція з Nuxt 3
> Повний посібник з міграції на Nuxt 4: нова структура app/, singleton-шар отримання даних, поверхнева реактивність за замовчуванням, розділення TypeScript-контексту, нормалізовані імена компонентів, Vue Router v5, зміни в управлінні head та контрольний список міграції.
- Published: 2026-05-01
- Updated: 2026-05-01
- Author: SharpSkill
- Tags: nuxt, vue, migration, typescript, tutorial
- Reading time: 10 min
---
Nuxt 4 являє собою найбільше архітектурне оновлення фреймворку з моменту виходу третьої версії. Нова структура каталогу `app/`, singleton-модель отримання даних, поверхнева реактивність за замовчуванням та розділений TypeScript-контекст змінюють підхід до організації й супроводу Vue-застосунків. Для розробників, які працюють з екосистемою Vue та Nuxt, глибоке розуміння цих змін є критично важливим як для повсякденної роботи, так і для підготовки до технічних співбесід. У цьому матеріалі розглядається кожна ключова зміна Nuxt 4 з практичними прикладами коду та покроковими інструкціями щодо міграції з Nuxt 3.
> **Автоматизований інструмент міграції**
>
> Nuxt 4 надає офіційний codemod для автоматичної реструктуризації каталогів. Перед початком ручної міграції варто запустити `npx codemod@latest nuxt/4/file-structure`, який автоматизує більшу частину структурних змін. Проте оновлення composable, конфігурація TypeScript та управління мета-тегами потребують ручного втручання.
## Нова структура каталогу app/
Найпомітніша зміна в Nuxt 4 полягає у переміщенні всіх клієнтських та серверних файлів застосунку до спеціалізованого каталогу `app/`. У Nuxt 3 компоненти, сторінки, лейаути, middleware та плагіни розміщувалися безпосередньо в кореневому каталозі проєкту. Nuxt 4 чітко розмежовує код застосунку від конфігураційних файлів, публічних ресурсів та серверного коду.
```text
my-nuxt-app/
├─ app/
│ ├─ assets/
│ ├─ components/
│ ├─ composables/
│ ├─ layouts/
│ ├─ middleware/
│ ├─ pages/
│ ├─ plugins/
│ ├─ utils/
│ ├─ app.vue
│ ├─ app.config.ts
│ └─ error.vue
├─ content/
├─ public/
├─ shared/ # New: code shared between app and server
├─ server/
└─ nuxt.config.ts
```
Новий каталог `shared/` є важливим архітектурним доповненням. Він дозволяє спільно використовувати типи, допоміжні функції та константи між кодом застосунку (`app/`) і серверним кодом (`server/`). У Nuxt 3 розробники змушені були дублювати типи на обох сторонах або створювати тимчасові рішення з відносними шляхами імпорту. Каталог `shared/` вирішує цю проблему на структурному рівні, забезпечуючи єдине джерело істини для спільного коду.
Файл `nuxt.config.ts` залишається в кореневому каталозі проєкту й не переміщується до `app/`. Аналогічно, каталоги `server/` та `public/` зберігають свої поточні розташування. Це розмежування чітко визначає зони відповідальності: `app/` містить код, що виконується у браузері та на SSR-сервері, `server/` зберігає бекенд-логіку, а `shared/` слугує мостом між цими двома шарами.
## Покрокова міграція з Nuxt 3
Процес міграції з Nuxt 3 на Nuxt 4 складається з кількох послідовних етапів. Першим кроком є оновлення фреймворку до останньої версії та дедуплікація залежностей.
```bash
# Upgrade Nuxt and deduplicate dependencies
npx nuxt upgrade --dedupe
```
Далі запускається офіційний codemod, який автоматично реструктурує файлову систему відповідно до нового стандарту. Codemod переносить файли до каталогу `app/`, оновлює шляхи імпорту та адаптує конфігурацію.
```bash
# Automate the directory restructuring
npx codemod@latest nuxt/4/file-structure
```
Для проєктів, які не можуть одразу перейти на нову структуру каталогів, Nuxt 4 пропонує опцію зворотної сумісності. Налаштування `srcDir` та `dir.app` у конфігурації дозволяє зберегти плоску структуру під час поступового переходу.
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
srcDir: '.',
dir: { app: 'app' },
})
```
Однак це тимчасове рішення. Команда Nuxt однозначно рекомендує повний перехід на структуру `app/`, оскільки майбутні версії фреймворку оптимізуватимуться саме під цю організацію. Крім того, інструменти екосистеми, зокрема Nuxt DevTools та модулі спільноти, вже починають приймати нову структуру як стандартну.
## Singleton-шар отримання даних та реактивні ключі
Nuxt 4 вносить фундаментальну зміну в роботу composable `useAsyncData` та `useFetch`. У Nuxt 3 виклик одного й того ж ключа даних з різних компонентів міг спричинити дублювання мережевих запитів та неузгодженість стану. Nuxt 4 впроваджує singleton-патерн: кожен унікальний ключ даних пов'язується рівно з одним екземпляром отримання даних, незалежно від кількості компонентів, що використовують ці дані.
Додатково `useAsyncData` отримує новий параметр `getCachedData` з контекстним об'єктом `ctx`, який повідомляє причину повторного виклику. Це дає змогу точно контролювати, коли використовувати кешовані дані, а коли виконувати новий запит.
```typescript
// app/composables/useProductData.ts
export function useProductData(productId: string) {
return useAsyncData(
`product-${productId}`,
() => $fetch(`/api/products/${productId}`),
{
getCachedData: (key, nuxtApp, ctx) => {
// ctx.cause tells why the fetch is happening
if (ctx.cause === 'refresh:manual') return undefined
return nuxtApp.payload.data[key]
},
},
)
}
```
Параметр `ctx.cause` може набувати значень `'refresh:manual'` (ручне оновлення, ініційоване розробником), `'refresh:hook'` (оновлення, ініційоване хуком життєвого циклу) або `'navigation'` (навігація між сторінками). Завдяки цьому composable може приймати обгрунтовані рішення щодо стратегії кешування: наприклад, завжди використовувати кеш при навігації, але примусово виконувати запит при ручному оновленні.
Singleton-патерн також усуває стани перегонів (race conditions). Коли кілька компонентів одночасно запитують однакові дані, Nuxt 4 виконує лише один запит і розподіляє результат між усіма підписниками. Такий підхід зменшує мережеве навантаження та забезпечує узгодженість даних у всьому застосунку.
## Поверхнева реактивність за замовчуванням
Одна з найвпливовіших змін у Nuxt 4 полягає в тому, що дані, повернуті `useAsyncData` та `useFetch`, за замовчуванням обгортаються у `shallowRef` замість `ref`. У Nuxt 3 використовувалася глибока реактивність, а це означало, що будь-яка зміна вкладених властивостей об'єкта автоматично ініціювала оновлення компонента. У Nuxt 4 повторний рендер відбувається лише при повній заміні значення `value`.
```typescript
// app/pages/dashboard.vue
```
Ця зміна має прямий вплив на продуктивність. Глибока реактивність створює проксі для кожного вкладеного об'єкта та масиву, що спричиняє значне навантаження на пам'ять та процесор при роботі з великими структурами даних. Поверхнева реактивність повністю усуває ці витрати, оскільки система реактивності Vue відстежує лише посилання верхнього рівня.
Для команд, що мігрують з Nuxt 3, це означає необхідність перевірки всіх ділянок коду, де вкладені властивості даних, отриманих через `useFetch` або `useAsyncData`, змінюються безпосередньо. Кожну таку мутацію потрібно замінити повною заміною значення (через spread-оператор) або явним увімкненням глибокої реактивності за допомогою опції `deep: true`.
## Розділення TypeScript-контексту (Context Splitting)
Замість єдиного глобального `tsconfig.json` Nuxt 4 розділяє конфігурацію TypeScript на чотири окремі контексти. Кожен контекст має власні правила розв'язання типів, що усуває проблему видимості серверних типів у клієнтському коді та навпаки.
```json
{
"files": [],
"references": [
{ "path": "./.nuxt/tsconfig.app.json" },
{ "path": "./.nuxt/tsconfig.server.json" },
{ "path": "./.nuxt/tsconfig.shared.json" },
{ "path": "./.nuxt/tsconfig.node.json" }
]
}
```
Контекст `app` охоплює код у каталозі `app/`, включаючи компоненти, сторінки та composable. Контекст `server` обслуговує файли в каталозі `server/` з доступом до типів Node.js та серверних API. Контекст `shared` забезпечує підтримку типів для каталогу `shared/`, видимих як з `app`, так і з `server`. Контекст `node` покриває конфігураційні файли, зокрема `nuxt.config.ts`.
Це розділення вимагає зміни способу запуску перевірки типів. Прапорець `-b` (режим компіляції проєктних посилань) для `vue-tsc` стає обов'язковим.
```bash
# Before (Nuxt 3)
nuxt prepare && vue-tsc --noEmit
# After (Nuxt 4)
nuxt prepare && vue-tsc -b --noEmit
```
Без прапорця `-b` компілятор TypeScript не розпізнає міжпроєктні посилання й повідомлятиме про помилки відсутніх типів. Це одна з найчастіше пропущених змін під час міграції, яка призводить до збоїв у CI/CD-конвеєрах.
## Нормалізовані імена компонентів та Vue Router v5
Nuxt 4 змінює правила іменування автоматично імпортованих компонентів. Компоненти у підкаталогах тепер отримують імена на основі повного шляху каталогу, а не лише імені файлу. Наприклад, компонент `components/dashboard/MetricsCard.vue` у Nuxt 3 був доступний як `DashboardMetricsCard` або `MetricsCard`. У Nuxt 4 дійсним є лише повне нормалізоване ім'я.
Ця зміна безпосередньо впливає на конфігурацію ``, де імена компонентів мають бути явно вказані у масивах `include` або `exclude`.
```vue
```
Необхідно перевірити імена компонентів, використані в `keepalive`, `` та динамічних компонентах (``), на відповідність новим нормалізованим іменам. Інакше KeepAlive припинить кешування компонентів, а анімовані переходи перестануть працювати.
Паралельно з цим Nuxt 4 інтегрує Vue Router v5, який вносить зміни в API навігації та механізми навігаційних гардів. Метод `router.resolve()` тепер повертає розширений об'єкт з додатковими метаданими. Навігаційні гарди отримали покращену типізацію параметрів. Командам, що використовують складні патерни маршрутизації, необхідно перевірити сумісність своїх гардів та middleware з новим API.
## Критичні зміни в управлінні head (Unhead v2)
Nuxt 4 переходить на Unhead v2, що вносить критичні зміни в управління мета-тегами та елементами ``. Властивості `vmid`, `hid`, `children` та `body`, які використовувалися в Nuxt 3 для визначення й дедуплікації тегів, видалено.
```typescript
// app/pages/product/[id].vue
```
Окрім того, деякі плагіни Unhead, зокрема `TemplateParamsPlugin` та `AliasSortingPlugin`, більше не завантажуються за замовчуванням. Якщо проєкт використовує шаблонні параметри у мета-тегах (наприклад, `%s | Назва сайту`), їх необхідно явно зареєструвати як Nuxt-плагін.
```typescript
// app/plugins/unhead.ts
import { TemplateParamsPlugin, AliasSortingPlugin } from '@unhead/vue/plugins'
export default defineNuxtPlugin({
setup() {
const unhead = injectHead()
unhead.use(TemplateParamsPlugin)
unhead.use(AliasSortingPlugin)
},
})
```
Симптом відсутньої реєстрації цих плагінів є досить підступним: шаблони заголовків не обробляються, і користувач бачить необроблений текст із символами `%s` замість сформованого заголовка. Ця проблема може не впливати на роботу застосунку в середовищі розробки, тому її складно виявити, поки не буде проаналізовано SEO-метрики в Google Search Console.
## Контрольний список міграції та типові пастки
Нижче наведено повний контрольний список для команд, що мігрують з Nuxt 3 на Nuxt 4. Кожен пункт має бути перевірений та підтверджений перед розгортанням у виробниче середовище.
1. **Оновлення Nuxt** -- запуск `npx nuxt upgrade --dedupe` та перевірка сумісності всіх залежностей з Nuxt 4
2. **Реструктуризація каталогів** -- запуск codemod або ручне переміщення файлів до каталогів `app/`, `shared/` та `server/`
3. **Перевірка шляхів імпорту** -- контроль оновлення всіх шляхів імпорту після переміщення файлів
4. **Оновлення composable отримання даних** -- перегляд усіх використань `useAsyncData` та `useFetch` з урахуванням нового API `getCachedData` та singleton-патерну
5. **Адаптація до shallow reactivity** -- виявлення та виправлення всіх місць, де вкладені властивості даних змінюються безпосередньо
6. **Конфігурація TypeScript** -- оновлення `tsconfig.json` до формату проєктних посилань та перехід `vue-tsc` на режим `-b`
7. **Імена компонентів** -- перевірка відповідності імен у `keepalive`, `` та динамічних компонентах новим нормалізованим іменам
8. **Мета-теги (Unhead v2)** -- видалення застарілих властивостей (`vmid`, `hid`, `children`, `body`) та реєстрація необхідних плагінів
9. **E2E-тести** -- запуск повного набору наскрізних тестів з урахуванням змін навігації Vue Router v5
10. **CI/CD-конвеєр** -- оновлення команд збірки та перевірки типів у конфігурації конвеєра
Найтиповіші пастки під час міграції:
- **Забуті мутації shallowRef** -- код виду `data.value.property = x`, що безпосередньо змінює вкладені властивості, не ініціює повторний рендер. Це найчастіше повідомлювана проблема після міграції
- **Відсутній прапорець `-b`** -- пропуск `-b` у команді `vue-tsc` спричиняє хибні помилки типів, які не видно локально, але з'являються в CI
- **Ненормалізовані імена у KeepAlive** -- KeepAlive мовчки ігнорує нерозпізнані імена, що призводить до втрати кешування без видимої помилки
- **Відсутні плагіни Unhead** -- непрацюючі шаблони заголовків перетворюються на SEO-проблему, яку можна виявити лише при аналізі результатів Google Search Console
Для поглиблення знань з екосистеми Vue та Nuxt рекомендується звернутися до [питання для співбесіди Vue/Nuxt](/technologies/vue-nuxt/interview-questions/nuxt-fundamentals) та [посібник з SSR та статичної генерації](/blog/vue-nuxt/nuxt-3-ssr-static-generation).
## Висновки
Nuxt 4 є значним кроком в еволюції фреймворку, що вносить зміни на кожному рівні процесу розробки. Основні висновки для підготовки до міграції та технічних співбесід:
- **Нова структура каталогу `app/`** чітко відокремлює код застосунку від конфігурації та серверних ресурсів; каталог `shared/` усуває дублювання типів між клієнтом та сервером
- **Singleton-шар отримання даних** забезпечує точний контроль над стратегією кешування через патерн `getCachedData` та контекстний об'єкт `ctx`, запобігаючи дублюванню мережевих запитів
- **Поверхнева реактивність за замовчуванням** суттєво підвищує продуктивність для великих структур даних, однак вимагає свідомої адаптації коду, що змінює вкладені властивості
- **Розділений TypeScript-контекст** забезпечує строгу ізоляцію типів між клієнтським, серверним та спільним кодом, усуваючи цілий клас типових помилок
- **Нормалізовані імена компонентів** та інтеграція Vue Router v5 вимагають перегляду конфігурації KeepAlive, анімованих переходів та навігаційних гардів
- **Unhead v2** зобов'язує явно реєструвати шаблонні плагіни та очищати застарілі властивості мета-тегів
- **Офіційний codemod** автоматизує реструктуризацію каталогів, проте зміни у composable, TypeScript та мета-тегах потребують ручної перевірки та адаптації
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/uk/blog/vue-nuxt/nuxt-4-directory-structure-migration