use cache - Nowa era cachowania w Next.js 16
Kurs Next.js · Moduł 9: Integracje i zaawansowane funkcje
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:
1// next.config.js
2module.exports = {
3 cacheComponents: true,
4};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
1// app/lib/data.ts
2async function getProducts() {
3 'use cache';
4
5 const response = await fetch('https://api.quantum-store.com/products');
6 return response.json();
7}Cachowanie całego pliku
1// app/lib/cached-data.ts
2'use cache';
3
4export async function getUsers() {
5 const response = await fetch('https://api.quantum-store.com/users');
6 return response.json();
7}
8
9export async function getOrders() {
10 const response = await fetch('https://api.quantum-store.com/orders');
11 return response.json();
12}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:
1import { cacheLife } from 'next/cache';
2
3async function getNews() {
4 'use cache';
5 cacheLife('minutes'); // cache na kilka minut
6
7 return fetch('https://api.quantum-news.com/latest').then(r => r.json());
8}
9
10async function getStaticContent() {
11 'use cache';
12 cacheLife('days'); // cache na dni
13
14 return fetch('https://api.quantum-cms.com/static').then(r => r.json());
15}
16
17async function getRealTimeData() {
18 'use cache';
19 cacheLife('seconds'); // cache na sekundy
20
21 return fetch('https://api.quantum-sensors.com/data').then(r => r.json());
22}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:
1// next.config.js
2module.exports = {
3 cacheComponents: true,
4 cacheLife: {
5 quantumFast: {
6 stale: 10, // sekundy - czas gdy dane są "świeże"
7 revalidate: 30, // sekundy - czas po którym rewalidacja w tle
8 expire: 300, // sekundy - maksymalny czas życia
9 },
10 quantumProducts: {
11 stale: 60,
12 revalidate: 300,
13 expire: 3600,
14 },
15 },
16};Użycie własnego profilu:
1import { cacheLife } from 'next/cache';
2
3async function getQuantumProducts() {
4 'use cache';
5 cacheLife('quantumProducts');
6
7 return fetch('https://api.quantum-store.com/products').then(r => r.json());
8}Inline konfiguracja
Możesz też definiować konfigurację bezpośrednio:
1import { cacheLife } from 'next/cache';
2
3async function getCriticalData() {
4 'use cache';
5 cacheLife({
6 stale: 5,
7 revalidate: 15,
8 expire: 60,
9 });
10
11 return fetch('https://api.quantum-critical.com/data').then(r => r.json());
12}cacheTag - Tagowanie i selektywna rewalidacja
cacheTag pozwala oznaczać cache tagami, które później mogą być użyte do selektywnej rewalidacji.
Podstawowe tagowanie
1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProduct(id: string) {
4 'use cache';
5 cacheTag(`product-${id}`);
6 cacheLife('hours');
7
8 return fetch(`https://api.quantum-store.com/products/${id}`).then(r => r.json());
9}
10
11async function getCategory(slug: string) {
12 'use cache';
13 cacheTag('categories', `category-${slug}`);
14 cacheLife('days');
15
16 return fetch(`https://api.quantum-store.com/categories/${slug}`).then(r => r.json());
17}Rewalidacja po tagach
1// app/actions/revalidate.ts
2'use server';
3
4import { revalidateTag, updateTag } from 'next/cache';
5
6export async function updateProduct(id: string, data: ProductData) {
7 // Aktualizacja produktu w bazie
8 await db.products.update(id, data);
9
10 // Rewalidacja cache dla tego produktu
11 updateTag(`product-${id}`);
12}
13
14export async function refreshAllCategories() {
15 // Rewalidacja wszystkich kategorii naraz
16 revalidateTag('categories', 'max');
17}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
1// app/lib/dashboard-data.ts
2import { cacheTag, cacheLife } from 'next/cache';
3
4// Dane produktów - cache na godziny, tagowane
5export async function getDashboardProducts() {
6 'use cache';
7 cacheTag('dashboard', 'products');
8 cacheLife('hours');
9
10 const response = await fetch('https://api.quantum-store.com/dashboard/products');
11 return response.json();
12}
13
14// Statystyki sprzedaży - cache na minuty (częste aktualizacje)
15export async function getSalesStats() {
16 'use cache';
17 cacheTag('dashboard', 'sales');
18 cacheLife('minutes');
19
20 const response = await fetch('https://api.quantum-store.com/dashboard/sales');
21 return response.json();
22}
23
24// Dane użytkowników - cache na dni
25export async function getUserStats() {
26 'use cache';
27 cacheTag('dashboard', 'users');
28 cacheLife('days');
29
30 const response = await fetch('https://api.quantum-store.com/dashboard/users');
31 return response.json();
32}1// app/actions/dashboard-actions.ts
2'use server';
3
4import { updateTag } from 'next/cache';
5
6export async function refreshDashboard() {
7 // Rewalidacja całego dashboardu
8 updateTag('dashboard');
9}
10
11export async function refreshSalesOnly() {
12 // Rewalidacja tylko sprzedaży
13 updateTag('sales');
14}1// app/dashboard/page.tsx
2import { getDashboardProducts, getSalesStats, getUserStats } from '@/lib/dashboard-data';
3import { refreshDashboard, refreshSalesOnly } from '@/actions/dashboard-actions';
4
5export default async function DashboardPage() {
6 const [products, sales, users] = await Promise.all([
7 getDashboardProducts(),
8 getSalesStats(),
9 getUserStats(),
10 ]);
11
12 return (
13 <div className="quantum-dashboard">
14 <header className="flex justify-between items-center">
15 <h1>Dashboard Quantum Store</h1>
16 <div className="flex gap-2">
17 <form action={refreshSalesOnly}>
18 <button type="submit">Odśwież sprzedaż</button>
19 </form>
20 <form action={refreshDashboard}>
21 <button type="submit">Odśwież wszystko</button>
22 </form>
23 </div>
24 </header>
25
26 <div className="grid grid-cols-3 gap-6">
27 <ProductsWidget data={products} />
28 <SalesWidget data={sales} />
29 <UsersWidget data={users} />
30 </div>
31 </div>
32 );
33}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):
1import { unstable_cache } from 'next/cache';
2
3const getCachedProducts = unstable_cache(
4 async () => {
5 return fetch('https://api.com/products').then(r => r.json());
6 },
7 ['products'],
8 { revalidate: 3600, tags: ['products'] }
9);Po (nowy sposób):
1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProducts() {
4 'use cache';
5 cacheTag('products');
6 cacheLife('hours');
7
8 return fetch('https://api.com/products').then(r => r.json());
9}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
1import React, { useState } from 'react';
2
3// use cache - Nowa era cachowania w Next.js 16
4// Demonstracja dyrektywy 'use cache' i jej konfiguracji
5
6export default function UseCacheDemo() {
7 const [cacheStrategy, setCacheStrategy] = useState('default');
8 const [data, setData] = useState<any>(null);
9 const [isFetching, setIsFetching] = useState(false);
10
11 const strategies = [
12 { id: 'default', label: 'Default Cache', ttl: '30s', description: 'Domyslne cachowanie z rewalidacja co 30s' },
13 { id: 'force-cache', label: 'Force Cache', ttl: 'infinite', description: 'Dane sa cachowane na stale' },
14 { id: 'no-store', label: 'No Store', ttl: '0', description: 'Brak cachowania - zawsze swierze dane' },
15 { id: 'revalidate', label: 'Revalidate', ttl: '60s', description: 'ISR - rewalidacja co 60 sekund' },
16 ];
17
18 // TODO: Zaimplementuj fetchWithCache - symuluj rozne strategie cachowania
19 // TODO: Pokaz roznice w czasach odpowiedzi dla roznych strategii
20
21 return (
22 <div style={{ background: '#0f0f23', minHeight: '100vh', padding: 20, color: '#e0e0e0', fontFamily: 'monospace' }}>
23 <h1 style={{ color: '#64ffda' }}>use cache - Next.js 16</h1>
24 {/* TODO: Selector strategii cachowania */}
25 {/* TODO: Przycisk "Pobierz dane" */}
26 {/* TODO: Wyswietl czas odpowiedzi i dane */}
27 {/* TODO: Porownanie strategii */}
28 </div>
29 );
30}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