JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Автоматическое кеширование fetch:

Автоматическое кеширование fetch: cache: "force-cache"

Модуль 4: Node.js, Next.js и Angular
9 уровень , 1 лекция
Открыта

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>
  );
}

Что произойдёт:

  1. Первый пользователь, открывший страницу, заставит сервер сделать реальный запрос к API.
  2. Второй, третий и все последующие пользователи увидят страницу, собранную на основе уже кешированных данных — запрос к API не будет выполняться заново.
  3. Если вы перезапустите сервер или произойдёт новая сборка — кеш сбросится и данные будут снова запрошены.

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 был одинаковым для идентичных запросов.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ