Кэширование в Next.js

Next.js улучшает производительность вашего приложения и снижает затраты за счёт кэширования результатов рендеринга и запросов данных. На этой странице представлено детальное описание механизмов кэширования в Next.js, API для их настройки и их взаимодействия между собой.

Полезно знать: Эта страница помогает понять внутреннюю работу Next.js, но не является обязательной для продуктивной работы. Большинство эвристик кэширования Next.js определяются использованием API и имеют настройки по умолчанию для оптимальной производительности с нулевой или минимальной конфигурацией. Если вы хотите сразу перейти к примерам, начните здесь.

Обзор

Вот высокоуровневый обзор различных механизмов кэширования и их назначения:

МеханизмЧто кэшируетсяГдеНазначениеДлительность
Мемоизация запросовВозвращаемые значения функцийСерверПовторное использование данных в дереве React-компонентовВ течение жизненного цикла запроса
Кэш данныхДанныеСерверХранение данных между запросами пользователей и деплоямиПостоянное (можно инвалидировать)
Полный кэш маршрутаHTML и полезная нагрузка RSCСерверСнижение затрат на рендеринг и повышение производительностиПостоянное (можно инвалидировать)
Кэш роутераПолезная нагрузка RSCКлиентСнижение количества запросов к серверу при навигацииСессия пользователя или по времени

По умолчанию Next.js кэширует максимально возможное количество данных для улучшения производительности и снижения затрат. Это означает, что маршруты рендерятся статически, а запросы данных кэшируются, если вы не отказались от этого. На диаграмме ниже показано поведение кэширования по умолчанию: когда маршрут рендерится статически во время сборки и когда статический маршрут посещается впервые.

Диаграмма, показывающая поведение кэширования по умолчанию в Next.js для четырёх механизмов, с HIT, MISS и SET во время сборки и при первом посещении маршрута.

Поведение кэширования меняется в зависимости от того, рендерится ли маршрут статически или динамически, кэшируются ли данные или нет, и является ли запрос частью первого посещения или последующей навигации. В зависимости от вашего случая использования вы можете настроить поведение кэширования для отдельных маршрутов и запросов данных.

Мемоизация запросов

Next.js расширяет API fetch для автоматической мемоизации запросов с одинаковым URL и параметрами. Это означает, что вы можете вызывать функцию fetch для одних и тех же данных в нескольких местах дерева React-компонентов, выполняя её только один раз.

Дедуплицированные Fetch-запросы

Например, если вам нужно использовать одни и те же данные в рамках маршрута (например, в Layout, Page и нескольких компонентах), вам не нужно получать данные на верхнем уровне дерева и передавать их через пропсы. Вместо этого вы можете получать данные в компонентах, которые в них нуждаются, не беспокоясь о производительности из-за нескольких одинаковых запросов.

async function getItem() {
  // Функция `fetch` автоматически мемоизируется, и результат
  // кэшируется
  const res = await fetch('https://.../item/1')
  return res.json()
}

// Эта функция вызывается дважды, но выполняется только первый раз
const item = await getItem() // cache MISS

// Второй вызов может быть в любом месте вашего маршрута
const item = await getItem() // cache HIT
async function getItem() {
  // Функция `fetch` автоматически мемоизируется, и результат
  // кэшируется
  const res = await fetch('https://.../item/1')
  return res.json()
}

// Эта функция вызывается дважды, но выполняется только первый раз
const item = await getItem() // cache MISS

// Второй вызов может быть в любом месте вашего маршрута
const item = await getItem() // cache HIT

Как работает мемоизация запросов

Диаграмма, показывающая, как работает мемоизация fetch во время рендеринга React.
  • Во время рендеринга маршрута при первом вызове конкретного запроса его результата не будет в памяти, и это будет MISS в кэше.
  • Поэтому функция будет выполнена, данные будут получены из внешнего источника, и результат будет сохранён в памяти.
  • Последующие вызовы этой функции в рамках того же прохода рендеринга будут HIT в кэше, и данные будут возвращены из памяти без выполнения функции.
  • После завершения рендеринга маршрута память "сбрасывается", и все записи мемоизации запросов очищаются.

Полезно знать:

  • Мемоизация запросов — это особенность React, а не Next.js. Она включена сюда, чтобы показать, как она взаимодействует с другими механизмами кэширования.
  • Мемоизация применяется только к методу GET в запросах fetch.
  • Мемоизация применяется только к дереву React-компонентов, это означает:
    • Она применяется к запросам fetch в generateMetadata, generateStaticParams, Layouts, Pages и других Server Components.
    • Она не применяется к запросам fetch в Route Handlers, так как они не являются частью дерева React-компонентов.
  • Для случаев, когда fetch не подходит (например, некоторые клиенты баз данных, CMS или GraphQL), вы можете использовать функцию cache React для мемоизации функций.

Длительность

Кэш существует в течение времени жизни серверного запроса до завершения рендеринга дерева React-компонентов.

Инвалидация

Поскольку мемоизация не распространяется между серверными запросами и применяется только во время рендеринга, её не нужно инвалидировать.

Отказ от использования

Мемоизация применяется только к методу GET в запросах fetch, другие методы, такие как POST и DELETE, не мемоизируются. Это поведение по умолчанию является оптимизацией React, и мы не рекомендуем от него отказываться.

Для управления отдельными запросами вы можете использовать свойство signal из AbortController. Однако это не отключит мемоизацию запросов, а лишь прервёт выполняющиеся запросы.

app/example.js
const { signal } = new AbortController()
fetch(url, { signal })

Кэш данных

Next.js имеет встроенный кэш данных, который сохраняет результаты запросов данных между входящими серверными запросами и деплоями. Это возможно благодаря тому, что Next.js расширяет нативный API fetch, позволяя каждому запросу на сервере устанавливать собственную семантику постоянного кэширования.

Полезно знать: В браузере опция cache в fetch указывает, как запрос будет взаимодействовать с HTTP-кэшем браузера, в Next.js опция cache указывает, как серверный запрос будет взаимодействовать с серверным кэшем данных.

Вы можете использовать опции cache и next.revalidate в fetch для настройки поведения кэширования.

Как работает кэш данных

Диаграмма, показывающая, как кэшированные и некэшированные fetch-запросы взаимодействуют с кэшем данных. Кэшированные запросы сохраняются в кэше данных и мемоизируются, некэшированные запросы получаются из источника данных, не сохраняются в кэше данных и мемоизируются.
  • При первом вызове запроса fetch с опцией 'force-cache' во время рендеринга Next.js проверяет кэш данных на наличие сохранённого ответа.
  • Если сохранённый ответ найден, он немедленно возвращается и мемоизируется.
  • Если сохранённый ответ не найден, запрос выполняется к источнику данных, результат сохраняется в кэше данных и мемоизируется.
  • Для некэшированных данных (например, без указания опции cache или с { cache: 'no-store' }) результат всегда получается из источника данных и мемоизируется.
  • Независимо от того, кэшированы данные или нет, запросы всегда мемоизируются, чтобы избежать дублирования запросов одних и тех же данных во время прохода рендеринга React.

Различия между кэшем данных и мемоизацией запросов

Хотя оба механизма кэширования помогают улучшить производительность за счёт повторного использования кэшированных данных, кэш данных сохраняется между входящими запросами и деплоями, тогда как мемоизация существует только в течение времени жизни запроса.

Длительность

Кэш данных сохраняется между входящими запросами и деплоями, пока вы не инвалидируете его или не откажетесь от использования.

Инвалидация

Кэшированные данные можно инвалидировать двумя способами:

  • Инвалидация по времени: Инвалидация данных после истечения определённого времени и выполнения нового запроса. Полезно для данных, которые меняются редко, и их актуальность не критична.
  • Инвалидация по требованию: Инвалидация данных на основе события (например, отправки формы). Инвалидация по требованию может использовать подход на основе тегов или путей для инвалидации групп данных одновременно. Полезно, когда нужно как можно быстрее показать самые свежие данные (например, при обновлении контента из headless CMS).

Инвалидация по времени

Для инвалидации данных через определённые интервалы времени вы можете использовать опцию next.revalidate в fetch для установки времени жизни ресурса в кэше (в секундах).

// Инвалидировать не чаще чем раз в час
fetch('https://...', { next: { revalidate: 3600 } })

Альтернативно, вы можете использовать опции конфигурации сегментов маршрута для настройки всех запросов fetch в сегменте или для случаев, когда вы не можете использовать fetch.

Как работает инвалидация по времени

Диаграмма, показывающая, как работает инвалидация по времени: после периода инвалидации возвращаются устаревшие данные при первом запросе, затем данные инвалидируются.
  • При первом вызове запроса fetch с revalidate данные будут получены из внешнего источника и сохранены в кэше данных.
  • Любые запросы, выполненные в течение указанного периода (например, 60 секунд), будут возвращать кэшированные данные.
  • После истечения периода следующий запрос всё равно вернёт кэшированные (теперь устаревшие) данные.
    • Next.js запустит фоновую инвалидацию данных.
    • После успешного получения данных Next.js обновит кэш данных свежими данными.
    • Если фоновая инвалидация не удастся, предыдущие данные останутся неизменными.

Это похоже на поведение stale-while-revalidate.

Инвалидация по требованию

Данные можно инвалидировать по требованию по пути (revalidatePath) или по тегу кэша (revalidateTag).

Как работает инвалидация по требованию

Диаграмма, показывающая, как работает инвалидация по требованию: кэш данных обновляется свежими данными после запроса на инвалидацию.
  • При первом вызове запроса fetch данные будут получены из внешнего источника и сохранены в кэше данных.
  • При запуске инвалидации по требованию соответствующие записи кэша будут удалены.
    • Это отличается от инвалидации по времени, которая сохраняет устаревшие данные в кэше до получения свежих.
  • При следующем запросе снова произойдёт MISS в кэше, и данные будут получены из внешнего источника и сохранены в кэше данных.

Отказ от использования

Если вы не хотите кэшировать ответ от fetch, вы можете сделать следующее:

let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })

Полный кэш маршрута

Связанные термины:

Вы можете встретить термины Автоматическая статическая оптимизация, Статическая генерация сайта или Статический рендеринг, используемые взаимозаменяемо для обозначения процесса рендеринга и кэширования маршрутов вашего приложения во время сборки.

Next.js автоматически рендерит и кэширует маршруты во время сборки. Это оптимизация, которая позволяет обслуживать кэшированный маршрут вместо рендеринга на сервере для каждого запроса, что приводит к более быстрой загрузке страниц.

Чтобы понять, как работает полный кэш маршрута, полезно посмотреть, как React обрабатывает рендеринг и как Next.js кэширует результат:

1. Рендеринг React на сервере

На сервере Next.js использует API React для организации рендеринга. Работа по рендерингу разделяется на части: по отдельным сегментам маршрута и границам Suspense.

Каждая часть рендерится в два этапа:

  1. React рендерит Server Components в специальный формат данных, оптимизированный для потоковой передачи, называемый React Server Component Payload.
  2. Next.js использует React Server Component Payload и инструкции JavaScript для Client Components, чтобы отрендерить HTML на сервере.

Это означает, что нам не нужно ждать завершения всего рендеринга перед кэшированием работы или отправкой ответа. Вместо этого мы можем передавать ответ по мере выполнения работы.

Что такое React Server Component Payload?

React Server Component Payload — это компактное бинарное представление отрендеренного дерева React Server Components. Оно используется React на клиенте для обновления DOM браузера. React Server Component Payload содержит:

  • Результат рендеринга Server Components
  • Заполнители для мест, где должны быть отрендерены Client Components, и ссылки на их JavaScript-файлы
  • Любые пропсы, переданные из Server Component в Client Component

Чтобы узнать больше, см. документацию по Server Components.

2. Кэширование Next.js на сервере (Полный кэш маршрута)

Поведение полного кэша маршрута по умолчанию, показывающее, как React Server Component Payload и HTML кэшируются на сервере для статически отрендеренных маршрутов.

Поведение Next.js по умолчанию — кэшировать результат рендеринга (React Server Component Payload и HTML) маршрута на сервере. Это применяется к статически отрендеренным маршрутам во время сборки или при инвалидации.

3. Гидратация и согласование React на клиенте

Во время запроса на клиенте:

  1. HTML используется для немедленного показа быстрого неинтерактивного начального превью Client и Server Components.
  2. React Server Components Payload используется для согласования деревьев Client и отрендеренных Server Components и обновления DOM.
  3. Инструкции JavaScript используются для гидратации Client Components и обеспечения интерактивности приложения.

4. Кэширование Next.js на клиенте (Кэш роутера)

React Server Component Payload сохраняется в клиентском кэше роутера — отдельном кэше в памяти, разделённом по отдельным сегментам маршрута. Этот кэш роутера используется для улучшения опыта навигации, сохраняя ранее посещённые маршруты и предзагружая будущие маршруты.

5. Последующие навигации

При последующих навигациях или предзагрузке Next.js проверит, сохранён ли React Server Components Payload в кэше роутера. Если да, он пропустит отправку нового запроса на сервер.

Если сегменты маршрута отсутствуют в кэше, Next.js получит React Server Components Payload с сервера и заполнит кэш роутера на клиенте.

Статический и динамический рендеринг

Будет ли маршрут закэширован во время сборки, зависит от того, является ли он статическим или динамическим. Статические маршруты кэшируются по умолчанию, тогда как динамические маршруты рендерятся во время запроса и не кэшируются.

На этой диаграмме показана разница между статическими и динамическими маршрутами с кэшированными и некэшированными данными:

Как статический и динамический рендеринг влияют на Full Route Cache. Статические маршруты кэшируются во время сборки или после ревалидации данных, тогда как динамические маршруты никогда не кэшируются

Узнайте больше о статическом и динамическом рендеринге.

Длительность

По умолчанию Full Route Cache является постоянным. Это означает, что результат рендеринга кэшируется между запросами пользователей.

Инвалидация

Есть два способа инвалидировать Full Route Cache:

  • Ревалидация данных: Ревалидация Data Cache приведёт к инвалидации Router Cache путём повторного рендеринга компонентов на сервере и кэширования нового результата рендеринга.
  • Повторное развертывание: В отличие от Data Cache, который сохраняется между развертываниями, Full Route Cache очищается при новых развертываниях.

Отказ от кэширования

Вы можете отказаться от Full Route Cache, другими словами, динамически рендерить компоненты для каждого входящего запроса, с помощью:

  • Использования Dynamic API: Это исключит маршрут из Full Route Cache и будет рендерить его динамически во время запроса. Data Cache по-прежнему может использоваться.
  • Использования опций конфигурации сегмента маршрута dynamic = 'force-dynamic' или revalidate = 0: Это пропустит Full Route Cache и Data Cache. То есть компоненты будут рендериться, а данные запрашиваться при каждом входящем запросе к серверу. Router Cache всё ещё будет применяться, так как это клиентский кэш.
  • Отказа от Data Cache: Если маршрут содержит fetch-запрос, который не кэшируется, это исключит маршрут из Full Route Cache. Данные для конкретного fetch-запроса будут запрашиваться при каждом входящем запросе. Другие fetch-запросы, которые не отказываются от кэширования, по-прежнему будут кэшироваться в Data Cache. Это позволяет использовать гибрид кэшированных и некэшированных данных.

Клиентский Router Cache

Next.js имеет клиентский кэш маршрутизатора в памяти, который хранит RSC-полезную нагрузку сегментов маршрута, разделённых по макетам, состояниям загрузки и страницам.

Когда пользователь переходит между маршрутами, Next.js кэширует посещённые сегменты маршрутов и предварительно загружает маршруты, по которым пользователь, скорее всего, перейдёт. Это обеспечивает мгновенную навигацию назад/вперёд, отсутствие полной перезагрузки страницы при переходах и сохранение состояния React и состояния браузера.

С Router Cache:

  • Макеты кэшируются и повторно используются при навигации (частичный рендеринг).
  • Состояния загрузки кэшируются и повторно используются при навигации для мгновенной навигации.
  • Страницы по умолчанию не кэшируются, но повторно используются при навигации назад и вперёд в браузере. Вы можете включить кэширование для сегментов страниц, используя экспериментальную опцию конфигурации staleTimes.

Полезно знать: Этот кэш специфичен для Next.js и Server Components и отличается от bfcache браузера, хотя даёт схожий результат.

Длительность

Кэш хранится во временной памяти браузера. Два фактора определяют, как долго длится кэш маршрутизатора:

  • Сессия: Кэш сохраняется при навигации. Однако он очищается при обновлении страницы.
  • Период автоматической инвалидации: Кэш макетов и состояний загрузки автоматически инвалидируется через определённое время. Длительность зависит от того, как ресурс был предварительно загружен, и был ли ресурс статически сгенерирован:
    • Стандартная предварительная загрузка (prefetch={null} или не указана): не кэшируется для динамических страниц, 5 минут для статических страниц.
    • Полная предварительная загрузка (prefetch={true} или router.prefetch): 5 минут для статических и динамических страниц.

Хотя обновление страницы очистит все кэшированные сегменты, период автоматической инвалидации влияет только на отдельный сегмент с момента его предварительной загрузки.

Полезно знать: Экспериментальная опция конфигурации staleTimes может использоваться для настройки упомянутых выше периодов автоматической инвалидации.

Инвалидация

Есть два способа инвалидировать Router Cache:

  • В Server Action:
    • Ревалидация данных по запросу по пути с помощью (revalidatePath) или по тегу кэша с помощью (revalidateTag)
    • Использование cookies.set или cookies.delete инвалидирует Router Cache, чтобы предотвратить устаревание маршрутов, использующих куки (например, аутентификацию).
  • Вызов router.refresh инвалидирует Router Cache и делает новый запрос к серверу для текущего маршрута.

Отказ от кэширования

Начиная с Next.js 15, сегменты страниц по умолчанию исключены из кэширования.

Полезно знать: Вы также можете отказаться от предварительной загрузки, установив свойство prefetch компонента <Link> в false.

Взаимодействие кэшей

При настройке различных механизмов кэширования важно понимать, как они взаимодействуют друг с другом:

Data Cache и Full Route Cache

  • Ревалидация или отказ от Data Cache приведёт к инвалидации Full Route Cache, так как результат рендеринга зависит от данных.
  • Инвалидация или отказ от Full Route Cache не влияет на Data Cache. Вы можете динамически рендерить маршрут, который содержит как кэшированные, так и некэшированные данные. Это полезно, когда большая часть вашей страницы использует кэшированные данные, но у вас есть несколько компонентов, которые зависят от данных, которые нужно запрашивать во время запроса. Вы можете динамически рендерить, не беспокоясь о влиянии на производительность из-за повторной загрузки всех данных.

Data Cache и клиентский Router Cache

  • Для немедленной инвалидации Data Cache и Router Cache вы можете использовать revalidatePath или revalidateTag в Server Action.
  • Ревалидация Data Cache в Route Handler не приведёт к немедленной инвалидации Router Cache, так как Route Handler не привязан к конкретному маршруту. Это означает, что Router Cache продолжит обслуживать предыдущую полезную нагрузку до полного обновления или истечения периода автоматической инвалидации.

API

В следующей таблице представлен обзор того, как различные API Next.js влияют на кэширование:

APIRouter CacheFull Route CacheData CacheReact Cache
<Link prefetch>Кэширование
router.prefetchКэширование
router.refreshРевалидация
fetchКэшированиеКэширование
fetch options.cacheКэширование или отказ
fetch options.next.revalidateРевалидацияРевалидация
fetch options.next.tagsКэшированиеКэширование
revalidateTagРевалидация (Server Action)РевалидацияРевалидация
revalidatePathРевалидация (Server Action)РевалидацияРевалидация
const revalidateРевалидация или отказРевалидация или отказ
const dynamicКэширование или отказКэширование или отказ
cookiesРевалидация (Server Action)Отказ
headers, searchParamsОтказ
generateStaticParamsКэширование
React.cacheКэширование
unstable_cacheКэширование

По умолчанию компонент <Link> автоматически предварительно загружает маршруты из Full Route Cache и добавляет полезную нагрузку React Server Component в Router Cache.

Чтобы отключить предварительную загрузку, вы можете установить свойство prefetch в false. Но это не отключит кэширование навсегда — сегмент маршрута всё равно будет кэшироваться на клиенте, когда пользователь посетит маршрут.

Узнайте больше о компоненте <Link>.

router.prefetch

Опция prefetch хука useRouter может использоваться для ручной предварительной загрузки маршрута. Это добавляет полезную нагрузку React Server Component в Router Cache.

См. справочник по API useRouter hook.

router.refresh

Опция refresh хука useRouter может использоваться для ручного обновления маршрута. Это полностью очищает Router Cache и делает новый запрос к серверу для текущего маршрута. refresh не влияет на Data Cache или Full Route Cache.

Результат рендеринга будет согласован на клиенте с сохранением состояния React и состояния браузера.

См. справочник по API useRouter hook.

fetch

Данные, возвращаемые fetch, не автоматически кэшируются в Data Cache.

Поведение кэширования fetch по умолчанию (например, когда опция cache не указана) эквивалентно установке опции cache в no-store:

let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })

См. справочник по API fetch для получения дополнительных опций.

fetch options.cache

Вы можете включить кэширование для отдельных fetch-запросов, установив опцию cache в force-cache:

// Включить кэширование
fetch(`https://...`, { cache: 'force-cache' })

См. справочник по API fetch для получения дополнительных опций.

fetch options.next.revalidate

Вы можете использовать опцию next.revalidate в fetch для установки периода ревалидации (в секундах) для отдельного fetch-запроса. Это ревалидирует Data Cache, что, в свою очередь, ревалидирует Full Route Cache. Будут загружены свежие данные, и компоненты будут перерендерены на сервере.

// Ревалидировать не чаще чем раз в час
fetch(`https://...`, { next: { revalidate: 3600 } })

См. справочник по API fetch для получения дополнительных опций.

fetch options.next.tags и revalidateTag

Next.js имеет систему тегирования кэша для детализированного кэширования и ревалидации данных.

  1. При использовании fetch или unstable_cache у вас есть возможность пометить записи кэша одним или несколькими тегами.
  2. Затем вы можете вызвать revalidateTag, чтобы очистить записи кэша, связанные с этим тегом.

Например, вы можете установить тег при загрузке данных:

// Кэшировать данные с тегом
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

Затем вызовите revalidateTag с тегом, чтобы очистить запись кэша:

// Ревалидировать записи с определённым тегом
revalidateTag('a')

Есть два места, где вы можете использовать revalidateTag, в зависимости от того, чего вы хотите достичь:

  1. Route Handlers — для ревалидации данных в ответ на событие от третьей стороны (например, вебхук). Это не приведёт к немедленной инвалидации Router Cache, так как Route Handler не привязан к конкретному маршруту.
  2. Server Actions — для ревалидации данных после действия пользователя (например, отправки формы). Это инвалидирует Router Cache для связанного маршрута.

revalidatePath

revalidatePath позволяет вручную ревалидировать данные и перерендерить сегменты маршрута ниже определённого пути одной операцией. Вызов метода revalidatePath ревалидирует Data Cache, что, в свою очередь, инвалидирует Full Route Cache.

revalidatePath('/')

Есть два места, где вы можете использовать revalidatePath, в зависимости от того, чего вы хотите достичь:

  1. Route Handlers — для ревалидации данных в ответ на событие от третьей стороны (например, вебхук).
  2. Server Actions — для ревалидации данных после взаимодействия пользователя (например, отправки формы, нажатия кнопки).

См. справочник по API revalidatePath для получения дополнительной информации.

revalidatePath vs. router.refresh:

Вызов router.refresh очистит Router Cache и перерендерит сегменты маршрута на сервере без инвалидации Data Cache или Full Route Cache.

Разница в том, что revalidatePath очищает Data Cache и Full Route Cache, тогда как router.refresh() не изменяет Data Cache и Full Route Cache, так как это клиентский API.

Dynamic APIs

Динамические API, такие как cookies и headers, а также свойство searchParams в страницах зависят от информации о входящем запросе во время выполнения. Их использование исключит маршрут из Full Route Cache, другими словами, маршрут будет рендериться динамически.

cookies

Использование cookies.set или cookies.delete в Server Action инвалидирует Router Cache, чтобы предотвратить устаревание маршрутов, использующих куки (например, для отражения изменений аутентификации).

См. справочник по API cookies.

Параметры конфигурации сегментов маршрута

Параметры конфигурации сегментов маршрута (Route Segment Config) могут использоваться для переопределения значений по умолчанию или когда невозможно использовать API fetch (например, при работе с клиентами баз данных или сторонними библиотеками).

Следующие параметры конфигурации отключают кеширование всего маршрута (Full Route Cache):

  • const dynamic = 'force-dynamic'

Этот параметр отключает кеширование данных для всех запросов (эквивалентно no-store):

  • const fetchCache = 'default-no-store'

Подробнее о расширенных настройках см. в документации fetchCache.

Другие доступные параметры описаны в документации Route Segment Config.

generateStaticParams

Для динамических сегментов (например, app/blog/[slug]/page.js) пути, указанные в generateStaticParams, кешируются в Full Route Cache во время сборки. При запросе Next.js также кеширует пути, которые не были известны во время сборки, при первом их посещении.

Для статического рендеринга всех путей во время сборки передайте полный список путей в generateStaticParams:

app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

Для статического рендеринга части путей во время сборки, а остальных — при первом посещении, верните частичный список путей:

app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  // Рендеринг первых 10 постов во время сборки
  return posts.slice(0, 10).map((post) => ({
    slug: post.slug,
  }))
}

Для статического рендеринга всех путей при первом посещении верните пустой массив (никакие пути не будут отрендерены во время сборки) или используйте export const dynamic = 'force-static':

app/blog/[slug]/page.js
export async function generateStaticParams() {
  return []
}

Важно: Функция generateStaticParams всегда должна возвращать массив, даже если он пустой. В противном случае маршрут будет рендериться динамически.

app/changelog/[slug]/page.js
export const dynamic = 'force-static'

Для отключения кеширования при запросе добавьте параметр export const dynamicParams = false в сегменте маршрута. При использовании этой настройки будут обслуживаться только пути, указанные в generateStaticParams, а остальные маршруты вернут 404 или будут обработаны (в случае catch-all маршрутов).

Функция cache в React

Функция cache в React позволяет мемоизировать возвращаемое значение функции, что позволяет вызывать одну и ту же функцию несколько раз, выполняя её только один раз.

Поскольку запросы fetch автоматически мемоизируются, оборачивать их в cache не требуется. Однако вы можете использовать cache для ручной мемоизации запросов данных в случаях, когда API fetch не подходит, например, при работе с клиентами баз данных, CMS или GraphQL.

import { cache } from 'react'
import db from '@/lib/db'

export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id })
  return item
})
import { cache } from 'react'
import db from '@/lib/db'

export const getItem = cache(async (id) => {
  const item = await db.item.findUnique({ id })
  return item
})