Kurs Next.js · Moduł 9: Integracje i zaawansowane funkcje
use cache - Nowa era cachowania w Next.js 16
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:
| Profil | stale | revalidate | expire | Opis |
|---|---|---|---|---|
default | 5min | 15min | nigdy | Profil użyty, gdy nie wywołasz cacheLife |
seconds | 30s | 1s | 60s | Dla szybko zmieniających się danych |
minutes | 5min | 1min | 1h | Dla danych aktualizowanych co kilka minut |
hours | 5min | 1h | 1d | Dla danych godzinowych |
days | 5min | 1d | 1w | Dla rzadko zmienianych danych |
weeks | 5min | 1w | 30d | Dla prawie statycznych danych |
max | 5min | 30d | 1y | Maksymalny 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
| Cecha | use cache | unstable_cache |
|---|---|---|
| Syntax | Dyrektywa | Funkcja wrapper |
| Konfiguracja czasu | cacheLife() | Opcje revalidate |
| Tagowanie | cacheTag() | tags w opcjach |
| Scope | Funkcja lub plik | Tylko funkcja |
| Status | Stabilne 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 -
cacheLifez profilami lub własną konfiguracją - Selektywną rewalidację -
cacheTagdo 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. 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