Incremental static regeneration

Incremental Static Regeneration (ISR) — это механизм, позволяющий обновлять статические страницы на лету без необходимости полной пересборки сайта. Он особенно полезен при работе с динамическим контентом, где нужно сочетать преимущества статической генерации и актуальности данных. В экосистеме JavaScript и MDX ISR позволяет поддерживать страницы с документацией, блогами или любым контентом, написанным в формате Markdown/MDX, актуальными без длительных билдов.


Основы ISR

В традиционном подходе к статической генерации (SSG) все страницы строятся во время сборки проекта. Это хорошо для небольших сайтов, но становится узким местом при больших объемах контента. ISR решает эту проблему следующим образом:

  1. Статическая генерация при первом запросе: Страница создается как статическая во время сборки или при первом запросе.

  2. Регистрация времени устаревания (revalidate): Для каждой страницы указывается период (в секундах), после которого следующая загрузка инициирует пересоздание страницы.

  3. Фоновое обновление контента: Новая версия страницы создается на сервере, а пользователи получают старую версию до завершения обновления. После завершения следующего запроса клиент получает уже свежую страницу.

Пример на JavaScript с использованием Next.js:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';

export async function getStaticProps() {
  const filePath = path.join(process.cwd(), 'content', 'article.mdx');
  const source = fs.readFileSync(filePath, 'utf8');
  const { content, data } = matter(source);
  const mdxSource = await serialize(content, { scope: data });

  return {
    props: {
      mdxSource,
      frontMatter: data,
    },
    revalidate: 60, // ISR: обновление каждые 60 секунд
  };
}

Ключевые моменты:

  • revalidate задает интервал обновления страницы.
  • MDX-контент сериализуется с помощью serialize.
  • Старые версии страниц доступны до завершения генерации новой.

Интеграция MDX с ISR

MDX позволяет встраивать React-компоненты прямо в Markdown. Использование ISR с MDX делает сайт интерактивным и динамически актуальным.

Пример использования компонентов MDX с ISR:

import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
import CustomButton from '../components/CustomButton';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

const components = { CustomButton };

export default function ArticlePage({ mdxSource }) {
  return <MDXRemote {...mdxSource} components={components} />;
}

export async function getStaticProps() {
  const filePath = path.join(process.cwd(), 'content', 'dynamic-article.mdx');
  const source = fs.readFileSync(filePath, 'utf8');
  const { content, data } = matter(source);
  const mdxSource = await serialize(content, { scope: data });

  return {
    props: { mdxSource },
    revalidate: 120, // Страница будет обновляться каждые 2 минуты
  };
}

Важные аспекты:

  • Компоненты React, такие как CustomButton, могут быть использованы внутри MDX.
  • revalidate контролирует частоту обновления контента.
  • MDX-контент и данные фронт-маттер автоматически сериализуются и передаются в компонент страницы.

Работа с большими коллекциями MDX

Для сайтов с большим количеством статических страниц (например, документация или блог) ISR помогает оптимизировать сборку:

  1. Использование getStaticPaths с fallback:
export async function getStaticPaths() {
  const files = fs.readdirSync(path.join(process.cwd(), 'content'));
  const paths = files.map((filename) => ({
    params: { slug: filename.replace('.mdx', '') },
  }));

  return { paths, fallback: 'blocking' };
}
  • fallback: 'blocking' позволяет строить страницы на лету при первом обращении, что совместимо с ISR.
  1. Комбинация с MDX: Каждая страница может иметь собственный фронт-маттер и контент, автоматически сериализуемый с serialize.

  2. Производительность: ISR позволяет избежать полной пересборки сайта при изменении одного файла MDX, значительно ускоряя развертывание.


Советы по эффективному использованию ISR с MDX

  • Оптимальный интервал revalidate: подбирается исходя из частоты обновления контента. Для документации 600–1800 секунд, для блога — 60–300 секунд.
  • Кэширование изображений и статических ассетов: ускоряет рендеринг страниц и снижает нагрузку на сервер при повторных запросах.
  • Комбинация ISR и динамических данных: можно объединять с API-запросами для отображения актуальных данных без полной пересборки MDX-контента.
  • Обработка ошибок: при сбое обновления ISR продолжает выдавать старую версию страницы, что обеспечивает стабильность сайта.

Преимущества ISR для MDX-контента

  • Скорость: страницы остаются статическими для пользователей, что снижает время загрузки.
  • Актуальность: контент автоматически обновляется в фоне.
  • Гибкость: поддержка React-компонентов внутри MDX делает контент интерактивным.
  • Масштабируемость: эффективно работает с сотнями и тысячами страниц.

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