1. Автоматическое кеширование в Next.js
Если бы каждый раз, когда пользователь открывает страницу, сервер заново запрашивал одни и те же данные из базы или внешнего API — мы бы очень быстро разорились на времени и ресурсах.
Когда вы вызываете fetch() в Server Component или на сервере в Next.js 15, Next.js по умолчанию старается кешировать результат этого запроса.
Это значит, что если на сервере за короткое время несколько пользователей или компонентов просят одни и те же данные — Next.js не будет каждый раз ходить на внешний сервер, а отдаст уже сохранённый результат.
Пример:
// app/page.tsx
export default async function HomePage() {
const res = await fetch('https://api.example.com/products');
const products = await res.json();
return (
<div>
<h1>Товары</h1>
<pre>{JSON.stringify(products, null, 2)}</pre>
</div>
);
}
Если кто-то ещё зайдёт на главную страницу (или вы обновите её), Next.js может вернуть данные из кеша, а не делать новый запрос к api.example.com.
Но... не всегда! Всё зависит от опции cache, которую можно явно указать во втором аргументе fetch.
2. Опция cache в fetch: что это такое?
В Next.js (и в стандартном fetch API) у функции fetch(url, options) есть опция cache, которая определяет, как сервер (или браузер) будет работать с кешем.
В Server Components Next.js поддерживает такие значения:
- "force-cache" — всегда использовать кеш, если он есть (по умолчанию).
- "no-store" — никогда не кешировать, всегда свежий запрос.
- "reload" — игнорировать кеш, всегда запрашивать заново (используется редко).
- "default" — стандартное поведение (в Next.js = "force-cache" для Server Components).
Важно:
В браузере эти опции работают иначе! В Next.js мы сейчас говорим только о серверной части.
cache: "force-cache" — как это работает?
Когда вы явно указываете cache: "force-cache", вы говорите Next.js:
"Пожалуйста, если у тебя есть свежий результат этого запроса — используй его, не делай новый запрос к серверу. Если нет — сходи за ним и положи в кеш".
const response = await fetch("https://api.example.com/products", {
cache: "force-cache"
});
Это поведение по умолчанию для Server Components.
То есть, если вы не указали опцию cache, Next.js будет вести себя так, как будто вы написали cache: "force-cache".
Что будет происходить:
- Первый запрос к этому URL — Next.js делает реальный запрос, кладёт результат в кеш.
- Все последующие запросы (в пределах одной сборки страницы/рендеринга) — Next.js возвращает данные из кеша.
- Если страница пересобирается (например, после деплоя или если вы явно сбросили кеш) — Next.js опять делает реальный запрос.
3. Пример: кеширование в действии
Давайте добавим в ваше учебное приложение страничку, где выводится список товаров из внешнего API. Мы хотим, чтобы эти данные не запрашивались заново при каждом заходе, а использовались из кеша.
app/products/page.tsx
export default async function ProductsPage() {
// Явно указываем cache: "force-cache", хотя это и так поведение по умолчанию
const res = await fetch('https://fakestoreapi.com/products', {
cache: 'force-cache'
});
const products = await res.json();
return (
<div>
<h1>Список товаров</h1>
<ul>
{products.map(product => (
<li key={product.id}>{product.title} — {product.price}$</li>
))}
</ul>
</div>
);
}
Что произойдёт:
- Первый пользователь, открывший страницу, заставит сервер сделать реальный запрос к API.
- Второй, третий и все последующие пользователи увидят страницу, собранную на основе уже кешированных данных — запрос к API не будет выполняться заново.
- Если вы перезапустите сервер или произойдёт новая сборка — кеш сбросится и данные будут снова запрошены.
4. Полезные нюансы
Когда кеш сбрасывается?
- Новая сборка приложения (например, после деплоя на Vercel или локально при изменении кода).
- Истёк срок жизни кеша (если вы используете advanced кеширование с revalidate — см. следующие лекции).
- Явный сброс через API (например, через revalidateTag()).
В обычной разработке:
Пока вы не изменили код страницы или не перезапустили сервер, кеш для fetch с "force-cache" будет работать.
Как проверить, что кеш работает?
Добавим в наш компонент небольшой "отладочный" вывод времени запроса:
export default async function ProductsPage() {
const start = Date.now();
const res = await fetch('https://fakestoreapi.com/products', {
cache: 'force-cache'
});
const products = await res.json();
const end = Date.now();
return (
<div>
<h1>Список товаров</h1>
<p>Время загрузки: {end - start} мс</p>
<ul>
{products.map(product => (
<li key={product.id}>{product.title} — {product.price}$</li>
))}
</ul>
</div>
);
}
Пояснение:
— Первый рендер страницы займёт больше времени (например, 200-500 мс).
— Второй и последующие рендеры (без изменений в коде) — мгновенно (1-5 мс), потому что данные берутся из кеша.
Лайфхак:
Можно посмотреть в консоли сервера, сколько реально времени уходит на запрос, или добавить console.log() перед и после fetch.
Когда НЕ стоит использовать cache: "force-cache"?
Если ваши данные часто меняются (например, это статистика, количество лайков, или новости), кеширование на долгое время может привести к тому, что пользователи будут видеть устаревшие данные.
В таких случаях используйте cache: "no-store" (см. следующую лекцию), чтобы всегда получать свежие данные.
Пример плохого использования:
— Онлайн-чат с кешированием сообщений — пользователи не увидят новые сообщения!
— Счётчик посещений, который не обновляется — бессмысленно.
Пример хорошего использования:
— Список товаров, который меняется раз в день.
— Страница с расписанием мероприятий на месяц вперёд.
— Любые "почти статические" данные.
Что кешируется? Только сами fetch-запросы!
Важно понимать: кешируется только результат вызова fetch с одинаковыми аргументами (URL + опции).
Если вы передадите другой URL или измените параметры — будет новый запрос и новый кеш.
await fetch('https://api.example.com/products', { cache: 'force-cache' }); // кеш #1
await fetch('https://api.example.com/products?category=books', { cache: 'force-cache' }); // кеш #2
Это два независимых кеша.
Если вы добавите динамические параметры (например, id пользователя), будет создаваться отдельный кеш для каждого варианта.
5. Типичные ошибки при работе с cache: "force-cache"
Ошибка №1: Ожидание мгновенного обновления данных
Многие новички думают, что если они обновят данные на сервере (например, добавят товар в базу), то сразу увидят изменения на сайте. Но если страница использует кеширование через "force-cache", пользователи будут видеть старые данные, пока кеш не сбросится (например, после деплоя).
Ошибка №2: Использование кеша для часто изменяющихся данных
Если вы кешируете данные, которые меняются каждую минуту, пользователи будут видеть устаревшую информацию. Для таких случаев лучше использовать "no-store" или более продвинутые механизмы revalidate.
Ошибка №3: Ожидание кеша в Client Components
Опция cache: "force-cache" работает только в Server Components и на сервере. В Client Components fetch не кешируется этим способом — там работает обычное поведение браузера.
Ошибка №4: Кеширование приватных/персональных данных
Если вы кешируете данные, которые зависят от пользователя (например, корзину покупок), вы рискуете показать чужие данные другим пользователям! Кешируйте только публичные, одинаковые для всех данные.
Ошибка №5: Изменение URL или опций fetch
Если вы случайно меняете порядок параметров или добавляете query-параметры, Next.js будет считать это новым запросом и создавать новый кеш. Следите, чтобы URL был одинаковым для идентичных запросов.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ