Пошук уроків, статей та іншого контенту
Налаштуйте runtime-параметри маршрутів, зокрема середовище виконання, динамічність і кешування.
У Next.js кожен маршрут може мати власні параметри виконання. Вони визначають:
де виконуватиметься код — у Node.js або Edge Runtime;
чи буде сторінка статичною або динамічною;
як довго Next.js зберігатиме результат і дані в кеші.
Конфігурація задається експортом спеціальних констант у файлі маршруту:
page.tsx;
layout.tsx;
route.ts.
Наприклад:
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
export const revalidate = 0Значення мають бути статичними. Не слід обчислювати їх під час виконання:
// Добре
export const revalidate = 60
// Не рекомендується
export const revalidate = 30 * 2Node.js є стандартним середовищем виконання для більшості маршрутів Next.js.
export const runtime = 'nodejs'Node.js підходить, коли маршрут:
використовує Node.js API;
працює з бібліотеками, які залежать від Node.js;
взаємодіє з файловою системою;
використовує драйвер бази даних із Node.js-залежностями.
Приклад маршруту API:
// app/api/health/route.ts
export const runtime = 'nodejs'
export async function GET() {
return Response.json({
status: 'ok',
runtime: 'nodejs',
time: new Date().toISOString(),
})
}Цей маршрут буде доступний за адресою /api/health.
Edge Runtime призначений для запуску коду ближче до користувача на edge-серверах:
export const runtime = 'edge'Edge Runtime підтримує Web API, наприклад:
Request;
Response;
fetch;
URL.
Водночас він не є повним середовищем Node.js. Node.js API та бібліотеки, які використовують модулі на кшталт fs, можуть бути недоступними.
Приклад Edge-маршруту:
// app/api/edge-time/route.ts
export const runtime = 'edge'
export async function GET() {
return Response.json({
runtime: 'edge',
time: new Date().toISOString(),
})
}Обирайте Edge Runtime лише тоді, коли всі залежності маршруту сумісні з ним.
Параметр dynamic визначає, як Next.js має рендерити маршрут.
export const dynamic = 'auto'Доступні значення:
auto — стандартний режим. Next.js сам визначає, чи можна статично згенерувати маршрут;
force-dynamic — маршрут рендериться для кожного запиту;
force-static — маршрут примусово робиться статичним;
error — Next.js викине помилку, якщо маршрут потребуватиме динамічного рендерингу.
dynamic = 'force-dynamic'Цей режим потрібен для сторінок із даними, які повинні бути актуальними під час кожного запиту:
// app/status/page.tsx
export const dynamic = 'force-dynamic'
export default function StatusPage() {
return (
<main>
<h1>Стан сервера</h1>
<p>Сторінку згенеровано: {new Date().toISOString()}</p>
</main>
)
}Якщо відкрити сторінку кілька разів, час генерування буде оновлюватися.
Такий режим доречний для:
персоналізованих сторінок;
сторінок із даними з cookies або headers;
інформації про поточну сесію;
даних, які не можна показувати з кешу.
dynamic = 'force-static'Цей режим примусово робить маршрут статичним:
// app/about/page.tsx
export const dynamic = 'force-static'
export default function AboutPage() {
return (
<main>
<h1>Про продукт</h1>
<p>Ця сторінка не залежить від даних запиту.</p>
</main>
)
}Використовуйте його для вмісту, який однаковий для всіх користувачів і не потребує виконання під час кожного запиту.
Якщо статичний маршрут намагається використати динамічні дані, наприклад cookies або headers, конфігурація може призвести до помилки або до некоректної логіки сторінки. Тому цей режим слід застосовувати лише тоді, коли статичність є свідомим рішенням.
dynamic = 'error'Цей режим корисний як перевірка того, що сторінка залишається статичною:
// app/docs/page.tsx
export const dynamic = 'error'
export default function DocsPage() {
return (
<main>
<h1>Документація</h1>
<p>Сторінка має бути повністю статичною.</p>
</main>
)
}Якщо код або залежність маршруту потребуватимуть динамічних даних, Next.js повідомить про це помилкою під час збірки або виконання.
revalidateПараметр revalidate задає інтервал повторної генерації статичного маршруту в секундах:
export const revalidate = 60Це означає, що згенерований результат може використовуватися протягом 60 секунд. Після завершення цього часу Next.js оновить його під час наступного запиту.
Приклад:
// app/news/page.tsx
export const revalidate = 300
export default function NewsPage() {
return (
<main>
<h1>Новини</h1>
<p>Дані цієї сторінки оновлюються приблизно кожні 5 хвилин.</p>
</main>
)
}Значення:
false — стандартний режим без заданого інтервалу повторної валідації;
0 — не кешувати результат маршруту, виконувати динамічний рендеринг;
додатне число — інтервал повторної валідації в секундах.
Для сторінки, яка повинна генеруватися під час кожного запиту, можна використати:
export const revalidate = 0Але для ясності зазвичай краще явно вказувати:
export const dynamic = 'force-dynamic'fetchКешування маршруту та кешування даних — пов’язані, але не тотожні поняття. Для конкретного запиту fetch можна задати власну політику.
Дані без кешу:
const response = await fetch('https://example.com/api/products', {
cache: 'no-store',
})Дані з повторною валідацією кожні 60 секунд:
const response = await fetch('https://example.com/api/products', {
next: {
revalidate: 60,
},
})Приклад серверної сторінки:
// app/products/page.tsx
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
type Product = {
id: number
name: string
}
async function getProducts(): Promise<Product[]> {
const response = await fetch('https://api.example.com/products', {
cache: 'no-store',
})
if (!response.ok) {
throw new Error('Не вдалося завантажити товари')
}
return response.json()
}
export default async function ProductsPage() {
const products = await getProducts()
return (
<main>
<h1>Товари</h1>
<ul>
{products.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</main>
)
}У цьому прикладі:
сторінка виконується в Node.js;
маршрут є динамічним;
запит до API не використовує кеш;
дані завантажуються під час кожного запиту до сторінки.
Якщо дані можна оновлювати періодично, конфігурацію можна змінити:
async function getProducts(): Promise<Product[]> {
const response = await fetch('https://api.example.com/products', {
next: {
revalidate: 300,
},
})
if (!response.ok) {
throw new Error('Не вдалося завантажити товари')
}
return response.json()
}Тепер Next.js може повторно використовувати результат запиту протягом приблизно 300 секунд.
Параметри можна комбінувати відповідно до потреб маршруту.
export const runtime = 'nodejs'
export const dynamic = 'auto'
export const revalidate = 60Це підходить для каталогу або публічної сторінки, де дані змінюються, але не повинні оновлюватися на кожен запит.
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
export const revalidate = 0Це підходить для кабінету користувача або сторінки, яка залежить від поточної сесії.
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export async function GET() {
const response = await fetch('https://example.com/api/status', {
cache: 'no-store',
})
return new Response(await response.text(), {
headers: {
'content-type': 'application/json',
},
})
}У такому маршруті немає Node.js-специфічних залежностей, тому він може працювати в Edge Runtime.
Перед вибором параметрів поставте собі три запитання:
Чи використовує маршрут Node.js API або Node.js-залежну бібліотеку?
Так — використовуйте runtime = 'nodejs'.
Ні — можна розглянути runtime = 'edge'.
Чи залежить результат від конкретного запиту або користувача?
Так — використовуйте dynamic = 'force-dynamic'.
Ні — залиште auto або використайте статичний режим.
Як часто дані повинні оновлюватися?
На кожен запит — cache: 'no-store' або динамічний маршрут.
Через певний інтервал — next.revalidate або revalidate.
Ніколи без нового деплою — статична генерація без періодичної валідації.
export const runtime = 'edge'
// Бібліотека або код із Node.js-залежністю може не працюватиЯкщо залежність використовує Node.js API, змініть runtime на nodejs або використовуйте сумісну бібліотеку.
fetchЯкщо запит використовує кешування, результат може бути не найновішим:
const response = await fetch('https://example.com/api/status')Для даних, які повинні бути актуальними під час кожного запиту, вкажіть:
const response = await fetch('https://example.com/api/status', {
cache: 'no-store',
})force-static для персоналізованої сторінкиСторінка з даними поточного користувача не повинна бути статичною для всіх:
// Неправильний вибір для персоналізованого вмісту
export const dynamic = 'force-static'Для персоналізованої сторінки використовуйте динамічний режим і контролюйте кешування даних.
Наприклад, якщо маршрут має:
export const dynamic = 'force-static'
export const revalidate = 0така конфігурація суперечить сама собі: перший параметр вимагає статичності, а другий вимикає кешування результату. Обирайте параметри відповідно до одного сценарію.
runtime = 'nodejs' запускає маршрут у повному Node.js Runtime.
runtime = 'edge' призначений для Edge Runtime і має обмеження щодо Node.js API.
dynamic = 'force-dynamic' змушує Next.js виконувати маршрут для кожного запиту.
dynamic = 'force-static' примусово робить маршрут статичним.
dynamic = 'error' допомагає перевірити, що маршрут не використовує динамічні можливості.
revalidate задає інтервал повторної генерації статичного результату.
cache: 'no-store' вимикає кешування конкретного запиту fetch.
next: { revalidate: seconds } дає змогу оновлювати кешовані дані через заданий інтервал.
Конфігурацію слід обирати з урахуванням залежностей маршруту, персоналізації та допустимої застарілості даних.