Про кэширование fetch() в Next.js
У некста 4 уровня кэширования, поэтому он считается темой со звездочкой при его изучении, хотя по идее база. В целом ничего сложного и полно обучалок, но многие путаются между слоями. Попробую сделать заметку-шпаргалку.
Сегодня будет про первые два уровня
Стандартный fetch в нексте переопределен, это все знают. Первый уровень кэширования fetch-запросов — Request Memoization. Под капотом — обычный React.cache(), который кэширует промис запроса в рамках рендера страницы. Т.е. если для одной страницы 5 раз вызывается fetch() с одинаковыми аргументами, то запрос отправится один раз, а остальные 4 запроса вернут промис из первого. Интересное: React.cache() сравнивает параметры по ссылке, и для него нужно выносить одинаковые объектные литералы в переменную, но fetch сериализует свои параметры, т.ч. можно не париться насчет одинаковых литералов.
Второй уровень: Data Cache — это кэширование ответа. Если Request Memoization не нашел промис такого же запроса, то fetch пойдет искать кэш ответа на диске. Найдет — отдаст и в сеть не пойдет. Не найдет — сделает запрос и сохранит ответ в Data Cache.
Как управлять этими кэшами? Request Memoization управлять нельзя, он всегда включен.
Для управления Data Cache есть три параметра:
1. cache 1.1 force-cache — навсегда кэширует запрос. Дефолтный вариант. 1.2 no-store — отключает Data Cache. 1.3. no-cache — выполняет запрос, если в ответе 304 Not Modified — читает ответ из Data Cache. 1.4. default — по дефолту то же что force-cache, но может быть переопределен некоторыми настройками кэша следующих уровней (потом расскажу). 1.5. reload — не читает, но пишет: делает запрос и обновляет ответ в Data Cache. 1.6. only-if-cached — не делает запрос вообще. Если в Data Cache нет данных — fetch падает с ошибкой.
2. next.revalidate 2.1. false — Data Cache хранится вечно, сбросить можно только вручную. 2.2. — количество секунд жизни кэша. Если время вышло, то следующий запрос обновит Data Cache, но сам вернет старую версию. Это называется stale-while-revalidate.
3. next.tags: string[] — можно пометить запрос тегами, а потом сбросить его кэш по этим тегам.
Как сбросить Data Cache вручную?
1. Параметр cache: ‘reload’ в следующем вызове fetch. См. выше п. 1.5.
2. revalidateTag(‘cheremsha’) — будет сброшен Data Cache всех запросов, которые мы пометили тегом cheremsha.
3. revalidatePath(‘/path’, ‘page’ | ‘layout’) — так мы сбросим Data Cache всех запросов, которые выполнялись для страницы /path. Если такие же запросы есть на других страницах — их это тоже коснется. Что касается второго аргумента: 3.1. page — сбрасываем только для указанной страницы. Дефолт. 3.2. layout — сбрасываем для указанной страницы и всех ее подстраниц: /path/subpath, /path/[id].
И последнее. При горизонтальном масштабировании Data Cache будет глючить, т.к. в каждом инстансе будет своя версия. Это одно из главных преимуществ хостинга некста на Vercel — там эта проблема решена. Однако решить можно и на своих серверах: нужно просто написать кастомный Cache Handler, чтобы изменить место хранения Data Cache на какой-нибудь Redis, например. Расскажу про это когда закончу истории про кэш.
В следующей серии будет про Full Route Cache.
· 23.07
Четкий пост. Спасибо за инфу!
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён