# Next.js 16.4: Cache Components тепер рекомендований default. Що це реально змінює?

> Next.js 16.4 рекомендує Cache Components для всіх застосунків, вмикає їх у нових проєктах і готує default у Next.js 17. Розбираємо use cache, нові гарантії та міграцію без магії.

- Автор: Юра Скиба (https://cookiesoftware.io)
- Опубліковано: 2026-10-15
- Категорія: React і Frontend
- Canonical: https://cookiesoftware.io/blog/nextjs-16-4-cache-components

---

Next.js 16.4 (вийшов 6 жовтня) офіційно рекомендує Cache Components як найкращу модель для кожного застосунку: нові проєкти через `create-next-app` отримують їх увімкненими, а в Next.js 17 це стане default для всіх. Якщо коротко, фреймворк остаточно йде від моделі «вгадай, кешується цей fetch чи ні» до моделі, де кеш – явна, декларативна властивість частини дерева компонентів. Це хороший напрям. Але слово «default» не означає «включи й забудь» – розбираємось, що реально змінюється і як мігрувати без сюрпризів.

## Що саме ввімкнули в 16.4

Найважливіша зміна 16.4 – не чергові відсотки швидкості Turbopack, а офіційна позиція команди. Дослівно з анонсу: «Starting with Next.js 16.4, we're excited to recommend Cache Components as the best choice for every Next.js app». До цього релізу рекомендація не була універсальною: у деяких сценаріях нова модель не давала тих самих гарантій вартості й продуктивності, що стара. 16.4 закриває ці прогалини, а Next.js 17 зробить модель дефолтною вже для всіх.

Сьогодні Cache Components вмикаються двома прапорцями в конфігу:

```ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
};

export default nextConfig;
```

Зверни увагу: Partial Prefetching тепер офіційно частина моделі, а не окрема опція. Як він працює, ми детально розбирали в [статті про Instant Navigations](/blog/nextjs-instant-navigations).

## Ментальна модель: кеш як властивість компонента

Команда Next.js пропонує думати про `'use cache'` як про компонентну версію HTTP-заголовка `Cache-Control`:

```tsx
import { cacheLife } from 'next/cache';

export default async function DashboardPage() {
  const currentUser = await getCurrentUser();

  return (
    <div>
      <p>Вітаю, {currentUser.name}</p>

      <Suspense fallback={<Loading />}>
        <Projects userId={currentUser.id} />
      </Suspense>
    </div>
  );
}

async function Projects({ userId }: { userId: string }) {
  'use cache';
  cacheLife('hours');

  return db.query.projects.findMany({
    where: eq(projectsTable.userId, userId),
  });
}
```

Одна сторінка поєднує персоналізовану request-time частину (привітання з іменем) і кешований UI (список проєктів живе годинами). Це ближче до того, як продуктовий інженер реально думає: не «ця route статична чи динамічна?», а «яка конкретно частина UI потребує свіжих даних?».

Семантику тегів, `revalidateTag`/`updateTag` і read-your-own-writes ми докладно розбирали в [ментальній моделі кешу Next.js](/blog/nextjs-cache-mental-model) – вона лишається чинною, 16.4 нічого в ній не ламає, лише додає гарантій зверху.

## ensureStatic: build-time guardrail замість тихої деградації

Найнедооціненіша фіча релізу. Стара болячка App Router: один випадково доданий динамічний компонент тихо міняв характеристики цілої сторінки – і твій «статичний» блог раптом рендериться на кожен request, а рахунок за compute росте.

Тепер це можна заборонити на рівні build:

```tsx
export const ensureStatic = 'navigation';

export default function Page() {
  return (
    <>
      <UserAvatar /> {/* 🔴 build впаде: динаміка у статичній route */}
      <Content />
    </>
  );
}
```

Значення три, за рівнем суворості: `'navigation'` (навігації на route ніколи не рендеряться на request), `'prefetch'` (префетчі тягнуть лише статичне) і `'shell'` (статичним гарантовано лише первинний shell). Можна ставити на layout – і тоді гарантія поширюється на всі сторінки під ним, аж до «увесь сайт статичний, окремі розділи – виняток».

Для блогу, маркетингових сторінок, документації чи ecommerce-категорій це саме той архітектурний контракт, який раніше жив тільки в головах: тепер його порушення ловить CI, а не рахунок наприкінці місяця.

## navigation() і prefetch(): явний бюджет на спекулятивну роботу

Prefetch – чудова річ, поки список із 50 посилань не вирішив завчасно завантажити пів бази даних. Класичний приклад з анонсу – inbox: хочеться префетчити перший екран повідомлення, але не тягнути entire thread для кожного видимого лінка.

```tsx
import { navigation } from 'next/cache';

async function Thread({ id }: { id: string }) {
  await navigation(); // виключає компонент із префетчу
  const thread = await getThread(id);
  // рендериться лише після реальної навігації
}
```

`await navigation()` каже: «цю частину не вантаж на prefetch, дочекайся справжнього переходу». Симетричний `await prefetch()` робить навпаки: виключає вміст із shell, відкладаючи його до явного префетчу.

Маленькі API з великою ідеєю: **спекулятивна робота має бути явним бюджетом**. Frontend performance давно не лише про bundle size – у server-centric фреймворку prefetch може покращити UX і одночасно роздути backend cost. Тепер цей компроміс контрольований.

## Як зламати собі кеш у перший день

1. **Масове додавання `'use cache'` у день міграції.** Спочатку розклади сторінки на три кошики: глобальні рідкозмінні дані, користувацькі повторно використовувані, request-specific/security-sensitive. Кешові межі малюються після цього, не до.
2. **Кешування того, що вимагає read-your-own-writes.** Користувач зберіг налаштування і бачить старі – це баг довіри, а не performance.
3. **Ігнорування `ensureStatic` на «очевидно статичних» сторінках.** Саме там він найдешевший: один рядок сьогодні проти тихої деградації через пів року.
4. **Сліпе оновлення у день релізу.** 16.4 стабільний, але питання в твоєму коді: у code review тепер питай не «чому це dynamic?», а «який freshness contract у цієї частини UI?».

## Тест-драйв на власному route

Візьми свій найбільш «гібридний» route (трохи персоналізації + багато спільного контенту) і випиши для кожної секції UI її freshness contract: скільки даним можна жити і хто їх інвалідує. Потім перевір, чи відповідає цьому фактична поведінка. Б'юсь об заклад, знайдеш щонайменше одну секцію, що рендериться на кожен request без жодної причини.

Найцікавіше в 16.4 – навіть не API, а напрям: App Router стає менш «framework decides» і більш «developer declares intent». Для тих, хто готується до співбесід із Next.js, базовий огляд моделі – у [гайді для React-розробника](/blog/nextjs-dlia-react-rozrobnyka).
