Стратегії повторної валідації в Next.js
Що таке повторна валідація?
Повторна валідація — це процес оновлення кешованих даних у Next.js. Це дозволяє підтримувати статично згенеровані сторінки свіжими без необхідності перебудови всього сайту. Next.js пропонує кілька стратегій повторної валідації.
Повторна валідація на основі часу
Автоматично повторно валідувати після вказаної кількості секунд:
// Використання fetch з повторною валідацією
async function getProducts() {
const res = await fetch("https://api.example.com/products", {
next: { revalidate: 3600 }, // Повторна валідація кожну годину
});
return res.json();
}
// Або на рівні сторінки/макета
export const revalidate = 3600; // Повторна валідація цієї сторінки кожну годинуЯк працює повторна валідація на основі часу
1. Перше запит → генерує сторінку, надає кешовану версію
2. До 1 години → надає кешовану версію (швидко!)
3. Після 1 години → перше запит все ще надає застарілий кеш
→ запускає фонову регенерацію
4. Наступне запит → надає свіжозгенеровану сторінкуЦе називається патерном stale-while-revalidate (SWR).
Повторна валідація за запитом
Повторна валідація негайно, коли дані змінюються:
revalidatePath
// app/api/webhook/route.ts
import { revalidatePath } from "next/cache";
export async function POST(request: Request) {
const data = await request.json();
// Оновлення бази даних...
await updateProduct(data);
// Повторна валідація конкретного шляху
revalidatePath("/products");
// Повторна валідація динамічного шляху
revalidatePath("/products/" + data.slug);
// Повторна валідація макета (всі сторінки, що його використовують)
revalidatePath("/products", "layout");
return Response.json({ revalidated: true });
}revalidateTag
// Позначте свої запити fetch
async function getProducts() {
const res = await fetch("https://api.example.com/products", {
next: { tags: ["products"] },
});
return res.json();
}
async function getProduct(id: string) {
const res = await fetch(`https://api.example.com/products/${id}`, {
next: { tags: ["products", `product-${id}`] },
});
return res.json();
}
// Повторна валідація всіх запитів, позначених "products"
import { revalidateTag } from "next/cache";
export async function POST() {
revalidateTag("products"); // Всі кеші, пов'язані з продуктами, оновлені
return Response.json({ revalidated: true });
}Серверні дії з повторною валідацією
"use server";
import { revalidatePath, revalidateTag } from "next/cache";
export async function createPost(formData: FormData) {
const title = formData.get("title") as string;
// Зберегти в базі даних
await db.insert(posts).values({ title });
// Повторна валідація
revalidateTag("posts");
revalidatePath("/blog");
}// Компонент клієнта, що використовує серверну дію
"use client";
export function CreatePostForm() {
return (
<form action={createPost}>
<input name="title" placeholder="Назва поста" />
<button type="submit">Створити</button>
</form>
);
}Порівняння
| Стратегія | Коли використовувати | Свіжість |
|---|---|---|
revalidate: false (або без опції) | Дані ніколи не змінюються | Статичні назавжди |
revalidate: N (секунди) | Дані змінюються періодично | Свіжі протягом N секунд |
revalidatePath() | Після конкретної мутації | Негайно |
revalidateTag() | Після змін у пов'язаних даних | Негайно, хірургічно |
cache: "no-store" | Завжди потрібні найновіші дані | В реальному часі (без кешу) |
Відмова від кешування
// Ніякого кешування — завжди отримуйте свіжі дані
async function getLatestPrices() {
const res = await fetch("https://api.example.com/prices", {
cache: "no-store",
});
return res.json();
}
// Або на рівні сторінки
export const dynamic = "force-dynamic";Важливо:
Використовуйте повторну валідацію на основі часу для даних, які змінюються періодично (наприклад, публікації в блозі, списки продуктів). Використовуйте повторну валідацію за запитом (revalidatePath/revalidateTag), коли ви точно знаєте, коли дані змінюються (наприклад, після надсилання форм, подій вебхуків). Поєднання дає вам статичну продуктивність з динамічною свіжістю.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.