Kurs Next.js · Moduł 9: Integracje i zaawansowane funkcje

use cache - Nowa era cachowania w Next.js 16

6 min czytania ·
W tej lekcji7

W serwerowniach Metropolii Quantum 2150, gdzie każda milisekunda ma znaczenie, poznasz rewolucyjne API cachowania, które pojawiło się eksperymentalnie w Next.js 15, a w Next.js 16 stało się częścią Cache Components. Dyrektywa use cache zastępuje przestarzałe unstable_cache i wprowadza znacznie bardziej intuicyjny sposób zarządzania pamięcią podręczną.

Czym jest dyrektywa use cache?

use cache to nowa dyrektywa (podobna do use server czy use client), która oznacza funkcje lub całe pliki jako cachowalne. Next.js automatycznie zarządza cyklem życia cache i rewalidacją.

Włączenie Cache Components

Aby korzystać z use cache, musisz najpierw włączyć w konfiguracji opcję cacheComponents:

// next.config.js
module.exports = {
  cacheComponents: true,
};

W Next.js 15 (w wersjach canary) ta sama funkcja kryła się pod eksperymentalnymi flagami experimental.dynamicIO i experimental.useCache. Next.js 16 usunął obie flagi, a cacheComponents nie jest tylko nową nazwą: włącza cały model Cache Components, który może ujawnić błędy budowania, jeśli trasa odczytuje niecachowane dane poza granicą <Suspense>.

Podstawowe użycie use cache

Cachowanie pojedynczej funkcji

// app/lib/data.ts
async function getProducts() {
  'use cache';

  const response = await fetch('https://api.quantum-store.com/products');
  return response.json();
}

Cachowanie całego pliku

// app/lib/cached-data.ts
'use cache';

export async function getUsers() {
  const response = await fetch('https://api.quantum-store.com/users');
  return response.json();
}

export async function getOrders() {
  const response = await fetch('https://api.quantum-store.com/orders');
  return response.json();
}

cacheLife - Kontrola czasu życia cache

Funkcja cacheLife pozwala precyzyjnie określić, jak długo dane powinny być przechowywane w cache.

Predefiniowane profile

Next.js dostarcza wbudowane profile czasowe:

import { cacheLife } from 'next/cache';

async function getNews() {
  'use cache';
  cacheLife('minutes'); // cache na kilka minut

  return fetch('https://api.quantum-news.com/latest').then(r => r.json());
}

async function getStaticContent() {
  'use cache';
  cacheLife('days'); // cache na dni

  return fetch('https://api.quantum-cms.com/static').then(r => r.json());
}

async function getRealTimeData() {
  'use cache';
  cacheLife('seconds'); // cache na sekundy

  return fetch('https://api.quantum-sensors.com/data').then(r => r.json());
}

Dostępne wbudowane profile:

ProfilstalerevalidateexpireOpis
default5min15minnigdyProfil użyty, gdy nie wywołasz cacheLife
seconds30s1s60sDla szybko zmieniających się danych
minutes5min1min1hDla danych aktualizowanych co kilka minut
hours5min1h1dDla danych godzinowych
days5min1d1wDla rzadko zmienianych danych
weeks5min1w30dDla prawie statycznych danych
max5min30d1yMaksymalny czas cache

Własne konfiguracje cacheLife

Możesz definiować własne profile w next.config.js:

// next.config.js
module.exports = {
  cacheComponents: true,
  cacheLife: {
    quantumFast: {
      stale: 10,      // sekundy - czas gdy dane są "świeże"
      revalidate: 30, // sekundy - czas po którym rewalidacja w tle
      expire: 300,    // sekundy - maksymalny czas życia
    },
    quantumProducts: {
      stale: 60,
      revalidate: 300,
      expire: 3600,
    },
  },
};

Użycie własnego profilu:

import { cacheLife } from 'next/cache';

async function getQuantumProducts() {
  'use cache';
  cacheLife('quantumProducts');

  return fetch('https://api.quantum-store.com/products').then(r => r.json());
}

Inline konfiguracja

Możesz też definiować konfigurację bezpośrednio:

import { cacheLife } from 'next/cache';

async function getCriticalData() {
  'use cache';
  cacheLife({
    stale: 5,
    revalidate: 15,
    expire: 60,
  });

  return fetch('https://api.quantum-critical.com/data').then(r => r.json());
}

cacheTag - Tagowanie i selektywna rewalidacja

cacheTag pozwala oznaczać cache tagami, które później mogą być użyte do selektywnej rewalidacji.

Podstawowe tagowanie

import { cacheTag, cacheLife } from 'next/cache';

async function getProduct(id: string) {
  'use cache';
  cacheTag(`product-${id}`);
  cacheLife('hours');

  return fetch(`https://api.quantum-store.com/products/${id}`).then(r => r.json());
}

async function getCategory(slug: string) {
  'use cache';
  cacheTag('categories', `category-${slug}`);
  cacheLife('days');

  return fetch(`https://api.quantum-store.com/categories/${slug}`).then(r => r.json());
}

Rewalidacja po tagach

// app/actions/revalidate.ts
'use server';

import { revalidateTag, updateTag } from 'next/cache';

export async function updateProduct(id: string, data: ProductData) {
  // Aktualizacja produktu w bazie
  await db.products.update(id, data);

  // Rewalidacja cache dla tego produktu
  updateTag(`product-${id}`);
}

export async function refreshAllCategories() {
  // Rewalidacja wszystkich kategorii naraz
  revalidateTag('categories', 'max');
}

W Next.js 16 masz do wyboru dwie funkcje. updateTag działa tylko w Server Actions i od razu wygasza cache, więc użytkownik widzi swoją zmianę jeszcze w tym samym żądaniu. revalidateTag z drugim argumentem 'max' oznacza dane jako nieaktualne i odświeża je w tle, pokazując do tego czasu starą wersję; wersja z jednym argumentem jest przestarzała.

Praktyczny przykład - Dashboard Quantum Store

// app/lib/dashboard-data.ts
import { cacheTag, cacheLife } from 'next/cache';

// Dane produktów - cache na godziny, tagowane
export async function getDashboardProducts() {
  'use cache';
  cacheTag('dashboard', 'products');
  cacheLife('hours');

  const response = await fetch('https://api.quantum-store.com/dashboard/products');
  return response.json();
}

// Statystyki sprzedaży - cache na minuty (częste aktualizacje)
export async function getSalesStats() {
  'use cache';
  cacheTag('dashboard', 'sales');
  cacheLife('minutes');

  const response = await fetch('https://api.quantum-store.com/dashboard/sales');
  return response.json();
}

// Dane użytkowników - cache na dni
export async function getUserStats() {
  'use cache';
  cacheTag('dashboard', 'users');
  cacheLife('days');

  const response = await fetch('https://api.quantum-store.com/dashboard/users');
  return response.json();
}
// app/actions/dashboard-actions.ts
'use server';

import { updateTag } from 'next/cache';

export async function refreshDashboard() {
  // Rewalidacja całego dashboardu
  updateTag('dashboard');
}

export async function refreshSalesOnly() {
  // Rewalidacja tylko sprzedaży
  updateTag('sales');
}
// app/dashboard/page.tsx
import { getDashboardProducts, getSalesStats, getUserStats } from '@/lib/dashboard-data';
import { refreshDashboard, refreshSalesOnly } from '@/actions/dashboard-actions';

export default async function DashboardPage() {
  const [products, sales, users] = await Promise.all([
    getDashboardProducts(),
    getSalesStats(),
    getUserStats(),
  ]);

  return (
    <div className="quantum-dashboard">
      <header className="flex justify-between items-center">
        <h1>Dashboard Quantum Store</h1>
        <div className="flex gap-2">
          <form action={refreshSalesOnly}>
            <button type="submit">Odśwież sprzedaż</button>
          </form>
          <form action={refreshDashboard}>
            <button type="submit">Odśwież wszystko</button>
          </form>
        </div>
      </header>

      <div className="grid grid-cols-3 gap-6">
        <ProductsWidget data={products} />
        <SalesWidget data={sales} />
        <UsersWidget data={users} />
      </div>
    </div>
  );
}

Różnice między use cache a unstable_cache

Cechause cacheunstable_cache
SyntaxDyrektywaFunkcja wrapper
Konfiguracja czasucacheLife()Opcje revalidate
TagowaniecacheTag()tags w opcjach
ScopeFunkcja lub plikTylko funkcja
StatusStabilne od Next.js 16 (Cache Components)Zastąpione przez use cache w Next.js 16

Migracja z unstable_cache

Przed (stary sposób):

import { unstable_cache } from 'next/cache';

const getCachedProducts = unstable_cache(
  async () => {
    return fetch('https://api.com/products').then(r => r.json());
  },
  ['products'],
  { revalidate: 3600, tags: ['products'] }
);

Po (nowy sposób):

import { cacheTag, cacheLife } from 'next/cache';

async function getProducts() {
  'use cache';
  cacheTag('products');
  cacheLife('hours');

  return fetch('https://api.com/products').then(r => r.json());
}

Podsumowanie

Dyrektywa use cache w Next.js 16 wprowadza:

  • Prostszą składnię - deklaratywne cachowanie z dyrektywą
  • Elastyczną kontrolę czasu - cacheLife z profilami lub własną konfiguracją
  • Selektywną rewalidację - cacheTag do precyzyjnego odświeżania
  • Lepszą wydajność - zoptymalizowane zarządzanie pamięcią podręczną

W Metropolii Quantum 2150, gdzie dane przepływają z prędkością światła, odpowiednie cachowanie to różnica między aplikacją błyskawiczną a taką, która ledwo zipie. Opanuj use cache i twoje aplikacje Next.js będą działać na najwyższych obrotach!

Kod do tej lekcji: App.tsx
import React, { useState } from 'react';

// use cache - Nowa era cachowania w Next.js 16
// Demonstracja dyrektywy 'use cache' i jej konfiguracji

export default function UseCacheDemo() {
  const [cacheStrategy, setCacheStrategy] = useState('default');
  const [data, setData] = useState<any>(null);
  const [isFetching, setIsFetching] = useState(false);

  const strategies = [
    { id: 'default', label: 'Default Cache', ttl: '30s', description: 'Domyslne cachowanie z rewalidacja co 30s' },
    { id: 'force-cache', label: 'Force Cache', ttl: 'infinite', description: 'Dane sa cachowane na stale' },
    { id: 'no-store', label: 'No Store', ttl: '0', description: 'Brak cachowania - zawsze swierze dane' },
    { id: 'revalidate', label: 'Revalidate', ttl: '60s', description: 'ISR - rewalidacja co 60 sekund' },
  ];

  // TODO: Zaimplementuj fetchWithCache - symuluj rozne strategie cachowania
  // TODO: Pokaz roznice w czasach odpowiedzi dla roznych strategii

  return (
    <div style={{ background: '#0f0f23', minHeight: '100vh', padding: 20, color: '#e0e0e0', fontFamily: 'monospace' }}>
      <h1 style={{ color: '#64ffda' }}>use cache - Next.js 16</h1>
      {/* TODO: Selector strategii cachowania */}
      {/* TODO: Przycisk "Pobierz dane" */}
      {/* TODO: Wyswietl czas odpowiedzi i dane */}
      {/* TODO: Porownanie strategii */}
    </div>
  );
}

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Co umożliwia dyrektywa 'use cache' w Next.js 16?

Zadania praktyczne w grze

  • Układanie w pionie

    Ułóż elementy w prawidłowej kolejności: export default → function Page() → {

  • Układanie w pionie

    Ułóż kroki integracji headless CMS z Next.js

Przydatne artykuły