Pull to refresh
96.13
MetaLamp
Доступно рассказываем о web3 и блокчейне

On-Demand ISR в Next.js или как эффективно обновлять статический контент на сайте, поступающий из CMS или админки

Reading time4 min
Views5.9K

Всем привет. Меня зовут Миша Якубчук, я Frontend разработчик из MetaLamp?.

В этой статье я расскажу, как и для чего, на одном из своих проектов, мы прикрутили новую возможность Next.js – On-Demand ISR (инкрементная статическая регенерация по запросу).

Проблема

В один из прекрасных солнечных дней к нам пришел заказчик с просьбой выполнить проект под ключ (фронтенд, бэкенд, дизайны и пр.). Одним из требований была админка, где помимо большого количества разного функционала, заказчик хотел возможность заполнения и редактирования seo-информации для страниц сайта. Это касалось как статических страниц («Главная», «Проекты»), так и динамических страниц для конкретного проекта, которые также создавались, редактировались и удалялись из админки. То есть, админ мог по своему желанию изменить значения мета-тегов для какой-либо страницы и новые значения должны были отобразиться на уже задеплоином сайте. 

Что мы уже знаем

Разработчики, использующие Next.js, наверняка знакомы с getStaticProps и скорее всего знакомы с обычным ISR.

Функция getStaticProps вызывается для страницы во время сборки проекта и генерирует статический HTML этой страницы, который сразу доступен для поисковых роботов. Таким образом внутри этой функции мы можем запросить, например, seo данные из админки или любую другую информацию, которую нам необходимо поместить в статический HTML. Вот пример для страницы home:

Пример использования функции getStaticProps
Пример использования функции getStaticProps

Отлично, данные получили, проект собрали, сайт задеплоили. Как теперь обновлять данные по мере их изменения в админке?

Существующий подход и его недостатки

Next.js уже на протяжении нескольких лет поддерживает так называемый ISR (инкрементная статическая регенерация). Чтобы включить эту возможность, достаточно указать свойство revalidate в getStaticProps с цифровым значением в секундах:

Скриншот из документации Next.js
Скриншот из документации Next.js

Каждый раз по истечению указанного времени и заходе пользователя на страницу, сервер Next.js будет регенерировать (пересобирать) страницу с новым вызовом getStaticProps, а значит новыми данными из админки. Во время регенерации пользователям будет показываться старая страница, а после – новая, с изменёнными данными. Всё это происходит фоном и не требует пересборки всего проекта. Этот механизм подробно описан в документации.

К сожалению, хоть это и решает нашу проблему, но довольно костыльно и есть большие НО:

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

  • Что если у нас большой трафик и большое количество страниц на сайте? Да ещё и с мультиязычностью. Скажем 50 страниц на 3х языках. Это уже 150 запросов на сервер с определённой периодичностью. К тому же 98% из этих запросов будут абсолютно лишними, так как совершенно точно админ не будет менять так часто данные на 150 страницах.

На самом деле нам просто нужно регенерировать страницу только тогда, когда админ изменил информацию. То есть по требованию.

Да здравствует On-Demand ISR.

Именно такую возможность добавили разработчики Next.js в версии 12.1.0 в качестве беты (февраль 2022) и зарелизили стабильную версию в 12.2.0 (июнь 2022). Как говорят сами разработчики – это была одна из самых востребованных функций за последнее время и они были рады (как и мы) наконец предоставить её. 

И так, теперь нам нужно, чтобы после того, как админ внёс изменения и нажал на кнопку “Save”, бэкенд послал запрос на фронтенд, тот его обработал бы и вызвал регенерацию необходимой страницы. 

Для этого в проекте Next.js мы добавим файл revalidate.ts по пути src/pages/api:

Пример обработки запроса на регенерирацию
Пример обработки запроса на регенерирацию

Сюда и будет делаться запрос, а именно на https://domain.com/api/revalidate. Запрос обрабатывается внутри функции handler.

Сама регенерация происходит посредством вызова функции res.unstable_revalidate(), куда в параметры необходимо передать путь к странице, которую необходимо регенерировать. Например res.unstable_revalidate(‘/ru/project/24’).

Примечание

Проект писался на Next.js 12.1.0, где данный функционал находился в бете, поэтому функция имеет приставку unstable. Начиная с версии 12.2.0 функция называется просто revalidate.

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

  • secret – приватный ключ, значение которого сравнивается с значением из переменной окружения на фронте и в случае несовпадения генерируется ошибка. 

  • key – ключ, содержащий название страницы, которую надо регенерировать.

  • lang – язык страницы, так как наш сайт мультиязычен и для каждого языка создаётся своя страница.

  • id – id конкретной страницы для динамических страниц.

В переменной revalidatePage формируется путь к странице, которую нужно обновить и далее передаётся в вызов функции res.unstable_revalidate(). Сервер Next.js запускает регенерацию страницы с новым вызовом getStaticProps и запросом на сервер за новой информацией.

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

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

Ссылка на документацию:

Tags:
Hubs:
Total votes 1: ↑1 and ↓0+1
Comments3

Articles

Information

Website
metalamp.ru
Registered
Employees
51–100 employees
Location
Россия