Кэш: 'use cache', теги и PPR
Cache Components, cacheLife, cacheTag, updateTag или revalidateTag.
Обновлено
Что такое кэш
Кэш = вы сохраняете результат дорогой операции (запрос к БД, запрос к API, рендер), чтобы не повторять её на каждый запрос. Итог: мгновенные страницы и меньше нагрузки на сервер.
Цена: данные в кэше могут устареть. Поэтому любому кэшу нужна стратегия инвалидации — когда выбрасывать старую копию.
Cache Components (Next 16)
Модель Next 16, включается в next.config.ts:
const nextConfig = { cacheComponents: true, partialPrefetching: true }Правило: по умолчанию ничего не кэшируется. Вы явно отмечаете, что кэшировать, директивой 'use cache'.
'use cache'
import { cacheLife, cacheTag } from 'next/cache'
export async function getPosts() {
'use cache'
cacheLife('hours') // сколько живёт
cacheTag('posts') // метка для инвалидации
return db.post.findMany()
}- Аргументы функции автоматически входят в ключ кэша:
getPost(1)иgetPost(2)— разные записи. - Ставится на функции данных, на компоненты или на всю страницу.
- Нельзя читать
cookies()/headers()внутри — читайте снаружи и передавайте значение аргументом.
Профили cacheLife
| Профиль | Ревалидация | Истечение | Для |
|---|---|---|---|
seconds |
1 с | 1 мин | почти в реальном времени (становится динамикой) |
minutes |
1 мин | 1 ч | ленты, цены |
hours |
1 ч | 1 день | редакционный контент (уроки здесь) |
days |
1 день | 1 неделя | редко меняющиеся страницы |
max |
30 дней | 1 год | почти статика |
Что такое Partial Prerendering
PPR сочетает статику и динамику на одной странице:
- При сборке Next рендерит всё, что может (включая то, что в
'use cache') → статическая оболочка, мгновенно отдаётся с CDN. - Динамические части (в
<Suspense>, читающие cookie и т. п.) рендерятся при запросе и передаются потоком.
Ровно это приложение: урок — в статической оболочке; ваш прогресс (из cookie) приходит потоком.
Вывод npm run build показывает тип каждого маршрута: ○ статика, ◐ partial prerender, ƒ динамика.
Инвалидация — виды и когда
| Функция | Где | Поведение | Когда |
|---|---|---|---|
updateTag('posts') |
только Server Actions | истекает сразу; следующий запрос ждёт новые данные | пользователь что-то изменил и должен сразу это увидеть (read-your-own-writes) |
revalidateTag('posts', 'max') |
Server Actions + Route Handlers | stale-while-revalidate: отдаёт старое, обновляет в фоне | контент из CMS / вебхука — небольшая задержка допустима |
revalidatePath('/blog') |
то же | инвалидирует весь маршрут | нет подходящих тегов |
refresh() |
Server Actions | перезапрашивает динамические данные текущей страницы | после мутаций без тега кэша (как сохранение прогресса здесь) |
Коротко
- По умолчанию ничего не кэшируется;
'use cache'+cacheLife+cacheTag— явно. - PPR = мгновенная статическая оболочка + динамические части потоком.
updateTag— для пользователя, который только что внёс изменение;revalidateTag(tag, 'max')— для остального.