13 - Кэширование Next.js и Динамические, Статические Страницы и Revalidate

Для доступа к видео войдите в систему

13 - Кэширование Next.js и Динамические, Статические Страницы и Revalidate

Оценить качество материала и подачу материала автором видео:

Front-end

Трудоустройтесь middle front-end разработчиком на React JS (TypeScript) за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Front-end

Back-end

Трудоустройтесь middle back-end разработчиком за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Back-end

Карьерный бустер

Получите коммерческий опыт на реальных стартапах, прокачайте tech & soft навыки, научитесь работать в команде, проходить собеседования и получите первую работу в IT!

Перейти на курс
Карьерный бустер

Основы Front-end

Сделайте первый шаг в IT, освоив базовые знания разработки и научившись создавать небольшие проекты на JavaScript

Перейти на курс
Основы Front-end

Основы Back-end

Сделайте первый шаг в IT, освоив базовые знания разработки. Без опыта. Без математики. Только практика: JavaScript, SQL, Node JS, база данных

Перейти на курс
Основы Back-end

Dynamic и static страницы, revalidate по времени

Автор конспекта: Стогниева Виктория

1. ⚙️ Статические и динамические страницы: поведение по умолчанию

1.1. 🔄 Разница между режимами разработки и продакшена

Поведение fetch-запросов кардинально отличается в зависимости от режима запуска приложения. Это важно понимать, чтобы избежать путаницы при разработке и деплое.

🧪 Режим разработки (npm run dev)

  • fetch всегда запрашивает свежие данные при каждом обращении к странице, создавая иллюзию динамической страницы. 🚀

🚀 Режим продакшена (npm run build)

  • fetch по умолчанию кэширует данные.
  • Запрос выполняется один раз во время сборки (build), и страница становится статической. 🧱

👉 Эта разница намеренная:

  • режим разработки — для удобства разработчика и быстрой обратной связи;
  • режим продакшена — для максимальной производительности за счет агрессивного кэширования. ⚡

1.2. 🏗️ Статическая генерация по умолчанию в продакшене

💡 Ключевая идея: любая страница, использующая fetch без дополнительных настроек, в продакшен-сборке становится статической.

Это означает, что:

  • данные запрашиваются только один раз — в момент сборки;
  • сгенерированная HTML-страница сохраняется и отдается всем пользователям без изменений до следующей пересборки.
💡

Страничка, которая сбилдилась в момент билда, будет отдаваться каждому пользователю каждый раз одинаковой.

1.3. 🤖 Когда страница становится динамической автоматически?

Next.js автоматически делает страницу динамической, если обнаруживает использование динамических API, например:

  • Динамические параметры маршрута (params.id);
  • cookies или headers;
  • Свойства соединения (Connection);
  • Параметры поиска URL (searchParams).

👉 В этих случаях Next.js понимает, что контент должен генерироваться индивидуально для каждого запроса, и отключает статическое кэширование. 🔓

2. 🗂️ Управление кэшем на уровне запроса (fetch)

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

2.1. 🔧 Опция cache

❌ cache: no-store

  • Полностью отключает кэширование.
  • Next.js выполняет запрос заново при каждом обращении к странице.
  • Делает всю страницу динамической, даже если остальные запросы могли быть статическими. 🌊
books\page.tsx
import { Todolists } from '@components/todolists/Todolists';
import type { Metadata } from 'next';
import styles from './page.module.css';
 
export const metadata: Metadata = {
  title: 'Books page',
  description: 'Generated by create next app books page',
};
 
export default async function Books() {
  const response = await fetch('https://jsonplaceholder.typicode.com/todos', {
    cache: 'no-store',
  });
  const todolists = await response.json();
 
  console.log('Fetched todolists');
 
  return (
    <div className={styles.page}>
      <main className={styles.main}>
        <Todolists todolists={todolists} />
      </main>
    </div>
  );
}

✅ cache: force-cache

  • Поведение по умолчанию в продакшене.
  • Next.js сначала ищет ответ в кэше:
  • если есть — берет из кэша;
  • если нет — делает сетевой запрос и сохраняет результат в кэш. 💾
books\page.tsx
export default async function Books() {
  const response = await fetch('https://jsonplaceholder.typicode.com/todos', {
    cache: 'force-cache',
  });
  const todolists = await response.json();
 
  console.log('Fetched todolists')

3. 🌍 Глобальное управление на уровне страницы (Route Segment Config)

Можно задать стратегию кэширования для всей страницы, экспортируя специальные константы из page.js.

3.1. 📌 Константа dynamic

auto (по умолчанию)

  • Next.js старается кэшировать максимум возможного и учитывает настройки каждого fetch.

force-dynamic

  • Аналог cache: 'no-store' для всех запросов.
  • Принудительно делает страницу динамической. 🔄
books\page.tsx
export const metadata: Metadata = {
  title: 'Books page',
  description: 'Generated by create next app books page',
};
 
export const dynamic = 'force-dynamic'
 
export default async function Books() {
  const response = await fetch('https://jsonplaceholder.typicode.com/todos');
  const todolists = await response.json();
 
  console.log('Fetched todolists')

force-static

  • Принудительно делает страницу статической, даже если используются динамические API (cookies, headers и т.д.).
  • Полезно в специфических случаях. 🧠

3.2. ⏱️ Константа revalidate

export const revalidate — глобальная настройка ревалидации по времени для всей страницы.

4. ⏳ Ревалидация по времени (Time-based Revalidation)

4.1. 🧩 Основная концепция

Ревалидация по времени позволяет кэшировать данные на определённый срок (например, 15 секунд). После истечения этого времени данные считаются «протухшими» и обновляются при следующем запросе. 🕒

4.2. 🛠️ Способы настройки

Можно задать ревалидацию:

  1. На уровне fetch:
books\page.tsx
import { Todolists } from "@components/todolists/Todolists"
import type { Metadata } from "next"
import fs from "fs/promises"
import path from "node:path"
import styles from "../page.module.css"
 
export const metadata: Metadata = {
  title: "Books page",
  description: "Generated by create next app books page",
}
 
export default async function Books() {
  const getParsedData = async () => {
    const filePath = path.join(process.cwd(), "public", "data.json")
    try {
      const data = await fs.readFile(filePath)
      return JSON.parse(data.toString())
    } catch {
      return { title: "no title" }
    }
  }
 
  const { title } = await getParsedData()
  console.log("Title:", title)
 
  const response = await fetch("https://jsonplaceholder.typicode.com/todos", {
    cache: "force-cache",
    next: { revalidate: 15 },
  })
  const todolists = await response.json()
 
  return (
    <div className={styles.page}>
      <main className={styles.main}>
        <div style={{ marginBottom: "30px", color: "yellow" }}>{title}</div>
        <Todolists todolists={todolists} />
      </main>
    </div>
  )
}

4.3. 🔁 Процесс ревалидации: пошаговый механизм

💡 Это ключевой момент для понимания. Процесс обновления данных происходит не мгновенно.

  1. 👉 Пользователь делает запрос к странице после того, как установленное время кэша истекло (например, 15 секунд). ⏳
  2. Next.js немедленно отдает старые закэшированные данные, чтобы ответ был максимально быстрым.
  3. ♻️ В фоновом режиме Next.js запускает процесс ревалидации:
  • выполняет все запросы заново,
  • генерирует новую версию страницы,
  • обновляет кэш. 💾
  1. Только следующий пользователь (или тот же пользователь при повторном запросе) получит обновлённую страницу из свежего кэша.

4.4. ⚠️ Особые значения для revalidate

🔹 revalidate = 0

  • 🚫 Запрещает кэширование.
  • Эквивалентно cache: 'no-store'.
  • Данные будут запрашиваться при каждом обращении к странице.

🔹 revalidate = false

  • 🔒 Кэшировать навсегда (вечный кэш, аналог Infinity).
  • Данные обновятся только при следующей пересборке проекта.

5. 🎯 Приоритет настроек ревалидации

📌 Главное правило: Если на странице задано несколько правил ревалидации, Next.jsвсегда выбирает наименьшее значение.

Пример:

  • На уровне страницы:
typescript
export const revalidate = 15

✅ Заключение: ключевые выводы

  1. 🔄 Разное поведение по умолчанию В режиме разработки fetch всегда динамический, что упрощает отладку. 🧪 В продакшене fetch по умолчанию статический и кэшируется при сборке для максимальной производительности. ⚡

  2. 🎛️ Гибкое управление кэшем Вы можете управлять кэшированием:

  • на уровне отдельных запросов (cache, next.revalidate), 🗂️
  • на уровне всей страницы через экспорт констант dynamic и revalidate. 🌍
  1. 🐢 Ревалидация не мгновенна После истечения срока кэша обновление происходит в фоне. Пользователь, инициировавший ревалидацию, сначала получает старые данные, а свежие будут доступны только при следующем запросе. 🔁