Полное руководство по инкрементной статической регенерации (ISR) с помощью Next.js

Опубликовано: 2022-03-10
Краткий обзор ↬ Incremental Static Regeneration (ISR) — это новая эволюция Jamstack, позволяющая мгновенно обновлять статический контент без необходимости полной перестройки вашего сайта. Гибридный подход Next.js позволяет вам использовать ISR для электронной коммерции, маркетинговых страниц, сообщений в блогах, медиа с рекламой и многого другого.

Год назад Next.js 9.3 выпустил поддержку Static Site Generation (SSG), что сделало его первым гибридным фреймворком. К этому моменту я уже несколько лет был счастливым пользователем Next.js, но этот релиз сделал Next.js моим новым решением по умолчанию. После интенсивной работы с Next.js я присоединился к Vercel, чтобы помогать таким компаниям, как Tripadvisor и Washington Post, внедрять и масштабировать Next.js.

В этой статье я хотел бы исследовать новую эволюцию Jamstack: Incremental Static Regeneration (ISR) . Ниже вы найдете руководство по ISR, включая варианты использования, демонстрации и компромиссы.

Проблема с генерацией статических сайтов

Идея, лежащая в основе Jamstack, привлекательна: предварительно обработанные статические страницы, которые можно отправить в CDN и сделать доступными по всему миру за считанные секунды. Статический контент работает быстро, устойчив к простоям и немедленно индексируется поисковыми роботами. Но есть некоторые проблемы.

Если вы приняли архитектуру Jamstack при создании крупномасштабного статического сайта, вы можете застрять на несколько часов, ожидая, пока ваш сайт будет построен. Если вы удвоите количество страниц, время сборки также удвоится. Давайте рассмотрим Target.com. Можно ли статически генерировать миллионы продуктов при каждом развертывании?

График времени сборки
Проблема с созданием статического сайта: поскольку время сборки линейно зависит от количества страниц, вы можете часами ждать, пока ваш сайт будет создан. (Большой превью)

Даже если каждая страница будет статически сгенерирована за нереальную 1 мс, на перестройку всего сайта все равно уйдут часы . Для больших веб-приложений выбор полной генерации статического сайта не является стартовым. Крупномасштабным командам требуется более гибкое, персонализированное гибридное решение.

Системы управления контентом (CMS)

Для многих команд контент сайта отделен от кода. Использование Headless CMS позволяет редакторам контента публиковать изменения без участия разработчика. Однако с традиционными статическими сайтами этот процесс может быть медленным.

Рассмотрим интернет-магазин со 100 000 товаров. Цены на товары часто меняются. Когда редактор контента меняет цену на наушники со 100 до 75 долларов в рамках рекламной акции, их CMS использует веб-хук для перестройки всего сайта. Невозможно ждать несколько часов, пока новая цена будет отражена.

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

Еще после прыжка! Продолжить чтение ниже ↓

Инкрементная статическая регенерация (ISR)

Next.js позволяет создавать или обновлять статические страницы после того, как вы создали свой сайт. Инкрементная статическая регенерация (ISR) позволяет разработчикам и редакторам контента использовать статическую генерацию для каждой страницы без необходимости перестраивать весь сайт . С ISR вы можете сохранить преимущества статики при масштабировании до миллионов страниц.

Статические страницы можно создавать во время выполнения (по запросу), а не во время сборки с помощью ISR. Используя аналитику, A/B-тестирование или другие метрики, вы можете найти компромисс в отношении времени сборки.

Рассмотрим магазин электронной коммерции с 100 000 товаров. При реалистичных 50 мс для статической генерации каждой страницы продукта это заняло бы почти 2 часа без ISR . С ISR мы можем выбирать из:

  • Более быстрые сборки
    Создайте 1000 самых популярных продуктов во время сборки. Запросы, сделанные к другим продуктам, будут пропущены из кеша и статически генерируются по запросу: 1-минутные сборки.
  • Более высокая частота попаданий в кэш
    Создавайте 10 000 продуктов во время сборки, гарантируя кэширование большего количества продуктов до запроса пользователя: 8-минутные сборки.
Иллюстрация, показывающая Jamstack слева и инкрементную статическую регенерацию справа.
Преимущество ISR: у вас есть возможность выбирать, какие страницы генерируются при сборке или по запросу. Выберите из (A) более быстрых сборок или (B) более кэшированных. (Большой превью)

Давайте рассмотрим пример ISR для страницы продукта электронной коммерции.

Начиная

Получение данных

Если вы никогда раньше не использовали Next.js, я бы порекомендовал прочитать «Начало работы с Next.js», чтобы понять основы. ISR использует тот же API Next.js для генерации статических страниц: getStaticProps . Указав revalidate: 60 , мы сообщаем Next.js о необходимости использования ISR для этой страницы.

Схема потока запросов для добавочной статической регенерации
Схема потока запросов для добавочной статической регенерации. (Большой превью)
  1. Next.js может определять время повторной проверки для каждой страницы. Давайте установим его на 60 секунд.
  2. Первоначальный запрос на страницу товара покажет кешированную страницу с исходной ценой.
  3. Данные о товаре обновляются в CMS.
  4. Любые запросы к странице после первоначального запроса и до 60 секунд кэшируются и выполняются мгновенно.
  5. После 60-секундного окна следующий запрос по-прежнему будет показывать кешированную (устаревшую) страницу. Next.js запускает регенерацию страницы в фоновом режиме .
  6. Как только страница будет успешно сгенерирована, Next.js аннулирует кеш и покажет обновленную страницу продукта. Если фоновая регенерация не удалась, старая страница остается неизменной.
 // pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }

Создание путей

Next.js определяет, какие продукты создавать во время сборки, а какие — по запросу. Давайте сгенерируем только 1000 самых популярных продуктов во время сборки, предоставив getStaticPaths список из 1000 самых популярных идентификаторов продуктов.

Нам нужно настроить, как Next.js будет «отступать» при запросе любого из других продуктов после первоначальной сборки. Есть два варианта на выбор: blocking и true .

  • fallback: blocking (предпочтительно)
    Когда делается запрос к странице, которая не была сгенерирована, Next.js будет отображать страницу на сервере по первому запросу. Будущие запросы будут обслуживать статический файл из кеша.
  • fallback: true
    Когда делается запрос к странице, которая не была сгенерирована, Next.js немедленно выдает статическую страницу с состоянием загрузки при первом запросе. Когда данные будут загружены, страница будет повторно отображена с новыми данными и кэширована. Будущие запросы будут обслуживать статический файл из кеша.
 // pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const paths = products.map((product) => ({ params: { id: product.id } })) return { paths, fallback: 'blocking' } }

Компромиссы

Next.js ориентирован в первую очередь на конечного пользователя. «Лучшее решение» относительно и зависит от отрасли, аудитории и характера приложения. Позволяя разработчикам переключаться между решениями, не выходя за рамки фреймворка, Next.js позволяет вам выбрать правильный инструмент для проекта.

Рендеринг на стороне сервера

ISR не всегда является правильным решением. Например, новостная лента Facebook не может отображать устаревший контент. В этом случае вы захотите использовать SSR и, возможно, ваши собственные заголовки cache-control с суррогатными ключами для аннулирования контента. Поскольку Next.js — это гибридный фреймворк, вы можете сами пойти на этот компромисс и остаться в рамках фреймворка.

 // You can cache SSR pages at the edge using Next.js // inside both getServerSideProps and API Routes res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');

SSR и пограничное кэширование аналогичны ISR (особенно при использовании заголовков кэширования stale-while-revalidate ), с основным отличием в первом запросе. С ISR первый запрос может быть гарантированно статическим, если он предварительно обработан. Даже если ваша база данных выйдет из строя или возникнут проблемы при обмене данными с API, ваши пользователи все равно будут видеть правильно обслуживаемую статическую страницу. Однако SSR позволит вам настроить свою страницу на основе входящего запроса.

Примечание . Использование SSR без кэширования может привести к снижению производительности. Каждая миллисекунда имеет значение при блокировании доступа пользователя к вашему сайту, и это может оказать существенное влияние на ваш TTFB (время до первого байта).

Генерация статического сайта

ISR не всегда имеет смысл для небольших веб-сайтов. Если ваш период повторной проверки больше, чем время, необходимое для восстановления всего вашего сайта, вы также можете использовать традиционную генерацию статического сайта.

Рендеринг на стороне клиента

Если вы используете React без Next.js, вы используете рендеринг на стороне клиента. Ваше приложение обслуживает состояние загрузки, за которым следует запрос данных внутри JavaScript на стороне клиента (например useEffect ). Хотя это увеличивает ваши возможности для хостинга (поскольку нет необходимости в сервере), есть компромиссы.

Отсутствие предварительно обработанного контента из исходного HTML приводит к более медленной и менее динамичной поисковой оптимизации (SEO). Также невозможно использовать CSR с отключенным JavaScript.

Резервные варианты ISR

Если ваши данные могут быть получены быстро, рассмотрите возможность использования fallback: blocking . Тогда вам не нужно учитывать состояние загрузки, и ваша страница всегда будет показывать один и тот же результат (независимо от того, кэширована она или нет). Если у вас медленная выборка данных, fallback: true позволяет вам немедленно показать пользователю состояние загрузки.

ISR: не только кэширование!

Хотя я объяснил ISR через контекст кеша, он предназначен для сохранения сгенерированных вами страниц между развертываниями. Это означает, что вы можете мгновенно откатиться и не потерять созданные ранее страницы.

Каждое развертывание может быть снабжено идентификатором, который Next.js использует для сохранения статически сгенерированных страниц. При откате вы можете обновить ключ, чтобы он указывал на предыдущее развертывание, что позволяет использовать атомарные развертывания. Это означает, что вы можете посетить свои предыдущие неизменяемые развертывания, и они будут работать так, как предполагалось.

  • Вот пример возврата кода с помощью ISR:
  • Вы отправляете код и получаете идентификатор развертывания 123.
  • На вашей странице опечатка «Smshng Magazine».
  • Вы обновляете страницу в CMS. Повторное развертывание не требуется.
  • Как только на вашей странице отображается «Smashing Magazine», он сохраняется в хранилище.
  • Вы отправляете какой-то плохой код и развертываете ID 345.
  • Вы выполняете откат к идентификатору развертывания 123.
  • Вы все еще видите «Smashing Magazine».

Возврат и сохранение статических страниц выходят за рамки Next.js и зависят от вашего хостинг-провайдера. Обратите внимание, что ISR отличается от серверного рендеринга с помощью заголовков Cache-Control , потому что срок действия кэшей истекает. Они не используются в разных регионах и будут удалены при возврате.

Примеры инкрементной статической регенерации

Инкрементная статическая регенерация хорошо работает для электронной коммерции, маркетинговых страниц, сообщений в блогах, медиа с рекламой и многого другого.

  • Демонстрация электронной коммерции
    Next.js Commerce — это универсальный стартовый набор для высокопроизводительных сайтов электронной коммерции.
  • Демонстрация реакций GitHub
    Реагируйте на исходную проблему GitHub и смотрите, как ISR обновляет статически сгенерированную целевую страницу.
  • Демонстрация статических твитов
    Этот проект развертывается за 30 секунд, но может статически генерировать 500 миллионов твитов по запросу с использованием ISR.

Изучите Next.js сегодня

Разработчики и большие команды выбирают Next.js за его гибридный подход и возможность поэтапного создания страниц по требованию. С ISR вы получаете преимущества статики с гибкостью серверного рендеринга. ISR работает из коробки, используя next start .

Next.js был разработан для постепенного внедрения. С Next.js вы можете продолжать использовать свой существующий код и добавлять столько (или меньше) React, сколько вам нужно. Начав с малого и постепенно добавляя больше страниц, вы можете предотвратить срыв работы функции, избегая полного переписывания. Узнайте больше о Next.js — и всем удачного программирования!

Дальнейшее чтение

  • Начало работы с Next.js
  • Сравнение методов оформления в Next.js
  • Как создать сервер GraphQL с использованием маршрутов API Next.js