Антон Ларичев
Одной из важных возможностей Next.js является ревалидация статических страниц после того, как мы их закэшировали на этапе сборки. То есть в рамках сборки мы получили кучу статических страниц, которые сложились в папку .next
в корне вашего проекта. Затем мы запустили сервер через next start
. Именно движок next обеспечивает нам ревалидацию наших страниц в фоне, незаметно для пользователя.
Запускаем ревалидацию
Для этого в функции получения статических свойств для страницы мы должны передать revalidate
и число секунд после которых будет происходить повторное выполнение функции и генерация обновлённой статической страницы:
export const getStaticProps: GetStaticProps = async () => {
// ...
return {
props: {
...data
},
revalidate: 5
};
};
Если быть точнее это будет работать следующем образом:
- Пользователь зашел на страницу.
- Произошло планирование ревалидации страницы через 5 секунд.
- Через 5 секунд страница обновилась в кэше next.js.
Важно заметить, что если заходов не будет страница не будет запланирована к ревалидации.
Итак, мы все сделали, заходим на страницу, а она не обновилась. Тому есть несколько возможным причин. С одной из них я столкнулся при разработке этого блога. Это и подвигло меня написать этот пост.
Статика вместо сервера Next
Ревалидация будет работать только если у вас запущен сервер next, который кроме того, что отдаёт эти страницы ещё и занят логикой ревалидации. Если вы вдруг сделали export и сами как-то размещаете статику о ревалидации можно забыть.
Заголовки nginx
Необходимо проверить, что nginx настроен правильно и там нет жёсткого кэширования ресурсов. К примеру такой заголовок не должен распространяться на html страницы:
Cache-Control: public, max-age=31536000
Кэш на сервере
Так как next при revalidate запрашивает данные с вашего сервера, нужно убедиться, что неверная работа с кэшом на сервере не препятствует обновлению данных. Для этого достаточно сделать curl запрос к вашему API и проверить что там данные обновились.
Кэш на клиенте
Если мы используем axios
или что-то подобное, которое не имеет кэша запросов, то проблем быть не должно. Но как только мы переходим к клиенту graphql, например apollo
, важно понимать, что там есть кэш. Именно это меня и подвело. Используемый код:
export const client = new ApolloClient({
cache: new InMemoryCache(),
link: authLink.concat(link),
});
И получение props:
export const getStaticProps: GetStaticProps = async () => {
const { data } = await client.query<{ findPosts: FindPostModel }>({
query: FIND_POSTS,
variables: {
limit: 10,
offset: 0
}
});
return {
props: {
...data.findPosts
},
revalidate: 1
};
};
С первого взгляда все нормально, мы просто клиентом выполняем запрос из NodeJS. Но InMemoryCache()
в результате сохраняется между revalidate
, так как запущен в одном процесс nodejs и создаётся только 1 раз при запуске next start
. Как решить?
const defaultOptions: DefaultOptions = {
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
};
export const client = new ApolloClient({
cache: new InMemoryCache(),
link: authLink.concat(link),
defaultOptions
});
Нам необходимо явно передать np-cache
для query. При этом, чтобы сделать верно для клиента, перед установкой этих параметров надо дополнительно проверить что код выполняется именно на сервер, например наличием window
.
Надеюсь эти советы помогут вас сэкономить время и быстрее найти ошибку.
Карта развития разработчика
Получите полную карту развития разработчика по всем направлениям: frontend, backend, devops, mobile
Комментарии
0