Получение, кэширование и перевалидизация данных
Получение данных является ключевой частью любого приложения. Эта страница описывает, как вы можете получать, кэшировать и перевалидировать данные в React и Next.js.
Существует четыре способа получения данных:
- На сервере, с помощью
fetch - На сервере, с помощью сторонних библиотек
- На клиенте, через обработчик маршрутов
- На клиенте, с помощью сторонних библиотек.
Получение данных на сервере с помощью fetch
Next.js расширяет родной fetch Веб-API, позволяя вам настроить поведение кэширования и перевалидизации для каждого запроса fetch на сервере. React расширяет fetch для автоматической кеширования запросов fetch во время отрисовки дерева компонентов React.
Вы можете использовать fetch с async/await в компонентах сервера, в обработчиках маршрутов и в действиях сервера.
Например:
async function getData() {
const res = await fetch('https://api.example.com/...')
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}Важно знать:
- Next.js предоставляет полезные функции, которые могут потребоваться при получении данных в компонентах сервера, такие как
cookiesиheaders. Они заставят маршрут динамически отрисовываться, поскольку зависят от информации о времени запроса.- В обработчиках маршрутов, запросы
fetchне кэшируются, так как обработчики маршрутов не являются частью дерева компонентов React.- В действиях сервера, запросы
fetchне кэшируются (по умолчаниюcache: no-store).- Чтобы использовать
async/awaitв компоненте сервера с TypeScript, вам потребуется использовать TypeScript5.1.3или более позднюю версию и@types/react18.2.8или более позднюю версию.
Кэширование данных
Кэширование хранит данные, поэтому их не нужно снова получать из источника данных при каждом запросе.
По умолчанию Next.js автоматически кэширует возвращаемые значения fetch в кэше данных на сервере. Это означает, что данные можно получить во время сборки или во время запроса, кэшировать и повторно использовать при каждом запросе данных.
// 'force-cache' is the default, and can be omitted
fetch('https://...', { cache: 'force-cache' })
Однако есть исключения, запросы fetch не кэшируются, когда:
- Используются внутри действия сервера.
- Используются внутри обработчика маршрута, который использует метод
POST.
Что такое кэш данных?
Кэш данных — это постоянный кэш HTTP. В зависимости от вашей платформы, кэш может масштабироваться автоматически и быть поделенным между несколькими регионами.
Узнайте больше о кэше данных.
Перевалидизация данных
Перевалидизация — это процесс очистки кэша данных и повторного получения последних данных. Это полезно, когда ваши данные меняются, и вы хотите убедиться, что показываете самую последнюю информацию.
Кэшированные данные могут быть перевалидированы двумя способами:
- Перевалидизация по времени: Автоматически перевалидирует данные через определенный промежуток времени. Это полезно для данных, которые меняются редко, и свежесть не так важна.
- Перевалидизация по требованию: Ручное перевалидирование данных на основе события (например, отправка формы). Перевалидизация по требованию может использовать подхода на основе тега или пути для перевалидирования групп данных сразу. Это полезно, когда вы хотите отобразить самые последние данные как можно скорее (например, когда контент из вашего headless CMS обновляется).
Перевалидизация по времени
Чтобы перевалидировать данные через определенный интервал времени, вы можете использовать параметр next.revalidate функции fetch для установки времени жизни ресурса в секундах.
fetch('https://...', { next: { revalidate: 3600 } })
В качестве альтернативы, для перевалидирования всех запросов fetch в сегменте маршрута, вы можете использовать Параметры конфигурации сегмента.
export const revalidate = 3600 // revalidate at most every hour
Если у вас есть несколько запросов fetch в статически отрисованном маршруте, и у каждого из них разная частота перевалидизации. Самое низкое время будет использоваться для всех запросов. Для динамически отрисованных маршрутов каждый запрос fetch будет перевалидироваться независимо.
Узнайте больше о перевалидизации по времени.
Перевалидизация по требованию
Данные могут быть перевалидированы по требованию по пути (revalidatePath) или по тегу кэша (revalidateTag) внутри действия сервера или обработчика маршрута.
Next.js имеет систему тегов кэша для аннулирования fetch запросов по всем маршрутам.
- При использовании
fetch, у вас есть возможность маркировать записи кэша одним или несколькими тегами. - Затем, вы можете вызвать
revalidateTagдля перевалидирования всех записей, связанных с этим тегом.
Например, следующий запрос fetch добавляет тег кэша collection.
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}Затем вы можете перевалидировать этот вызов fetch помеченный тегом collection, вызвав revalidateTag в действии сервера:
'use server'
import { revalidateTag } from 'next/cache'
export default async function action() {
revalidateTag('collection')
}Узнайте больше о перевалидизации по требованию.
Обработка ошибок и перевалидизация
Если при попытке перевалидировать данные возникает ошибка, последние успешно сгенерированные данные продолжат подаваться из кэша. При следующем запросе Next.js повторно попытается перевалидировать данные.
Отключение кэширования данных
Запросы fetch не кэшируются, если:
- Ключевое слово
cache: 'no-store'добавлено к запросамfetch. - Параметр
revalidate: 0добавлен к отдельным запросамfetch. - Запрос
fetchнаходится внутри обработчика маршрута, который использует методPOST. - Запрос
fetchследует за использованиемheadersилиcookies. - Используется опция сегмента маршрута
const dynamic = 'force-dynamic'. - Опция сегмента маршрута
fetchCacheнастраивается для пропуска кэша по умолчанию. - Запрос
fetchиспользует заголовкиAuthorizationилиCookieи существует запрос выше его в дереве компонентов, который не был кэширован.
Отдельные запросы fetch
Чтобы отключить кэширование для отдельных запросов fetch , вы можете установить параметр cache в запросе fetch в значение 'no-store'. Это позволит динамически получать данные при каждом запросе.
fetch('https://...', { cache: 'no-store' })Просмотрите все доступные параметры cache в fetch справке по API.
Множественные запросы fetch
Если у вас есть несколько запросов fetch в сегменте маршрута (например, макет или страница), вы можете настроить поведение кэширования всех запросов данных в сегменте, используя Параметры конфигурации сегмента.
Однако мы рекомендуем настроить поведение кэширования каждого запроса fetch индивидуально. Это даст вам более точный контроль над поведением кэширования.
Получение данных на сервере с помощью сторонних библиотек
В случаях, когда вы используете стороннюю библиотеку, которая не поддерживает или не предоставляет fetch (например, базу данных, CMS или клиент ORM), вы можете настроить поведение кэширования и перевалидизации этих запросов, используя Параметры конфигурации сегмента маршрута и функцию React cache.
Будет ли кэшироваться информация или нет, будет зависеть от того, является ли сегмент маршрута статически или динамически отрисованным. Если сегмент статический (по умолчанию), вывод запроса будет кэширован и перевалидирован как часть сегмента маршрута. Если сегмент динамический, вывод запроса не будет кэширован и будет повторно получен при каждом запросе при отрисовке сегмента.
Вы также можете использовать экспериментальный unstable_cache API.
Пример
В приведенном ниже примере:
- Функция React
cacheиспользуется для кеширования запросов данных. - Параметр
revalidateустановлен в значение3600в сегментах макета и страницы, что означает, что данные будут кэшироваться и перевалидироваться не чаще, чем раз в час.
import { cache } from 'react'
export const getItem = cache(async (id: string) => {
const item = await db.item.findUnique({ id })
return item
})Хотя функция getItem вызывается дважды, только один запрос будет отправлен в базу данных.
import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // revalidate the data at most every hour
export default async function Layout({
params: { id },
}: {
params: { id: string }
}) {
const item = await getItem(id)
// ...
}import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // revalidate the data at most every hour
export default async function Page({
params: { id },
}: {
params: { id: string }
}) {
const item = await getItem(id)
// ...
}Получение данных на клиенте с помощью обработчиков маршрутов
Если вам нужно получить данные в компоненте клиента, вы можете вызвать Обработчик маршрута из клиента. Обработчики маршрутов выполняются на сервере и возвращают данные клиенту. Это полезно, когда вы не хотите предоставлять клиенту конфиденциальную информацию, например, токены API.
См. документацию Обработчика маршрута для примеров.
Компоненты сервера и обработчики маршрутов
Поскольку компоненты сервера отображаются на сервере, вам не нужно вызывать обработчик маршрута из компонента сервера для получения данных. Вместо этого вы можете получить данные непосредственно внутри компонента сервера.
Получение данных на клиенте с помощью сторонних библиотек
Вы также можете получить данные на клиенте, используя стороннюю библиотеку, такую как SWR или TanStack Query. Эти библиотеки предоставляют свои собственные API для запоминания запросов, кэширования, перепроверки и изменения данных.
Будущие API:
use— это функция React, которая принимает и обрабатывает промис, возвращаемый функцией. Оборачиваниеfetchвuseв настоящее время не рекомендуется в компонентах клиента и может вызвать несколько повторных рендерингов. Узнайте больше оuseв документации React.
© 2024 Vercel, Inc.
Licensed under the MIT License.
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating