Частичный предварительный рендеринг

До этого момента вы узнали о статическом и динамическом рендеринге, а также о потоковой передаче динамического контента, зависящего от данных. В этой главе давайте разберёмся, как объединить статический рендеринг, динамический рендеринг и потоковую передачу в одном маршруте с помощью частичного предварительного рендеринга (PPR).

Частичный предварительный рендеринг — это экспериментальная функция, представленная в Next.js 14. Содержание этой страницы может обновляться по мере стабилизации функции. PPR доступен только в канареечных релизах Next.js (next@canary), но не в стабильной версии Next.js. Мы пока не рекомендуем использовать частичный предварительный рендеринг в продакшене.

Чтобы установить канареечный релиз Next.js, выполните:

pnpm install next@canary

Статические vs. динамические маршруты

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

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

Вернёмся к вашей странице дашборда. Какие компоненты вы бы отнесли к статическим, а какие — к динамическим?

Когда будете готовы, нажмите кнопку ниже, чтобы увидеть, как можно разделить маршрут дашборда:

Что такое частичный предварительный рендеринг?

Next.js 14 представил экспериментальную версию частичного предварительного рендеринга — новой модели рендеринга, которая позволяет объединить преимущества статического и динамического рендеринга в одном маршруте. Например:

Частично предварительно отрендеренная страница продукта с статичной навигацией и информацией о продукте, а также динамической корзиной и рекомендуемыми товарами

Когда пользователь посещает маршрут:

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

Как работает частичный предварительный рендеринг?

Частичный предварительный рендеринг использует Suspense от React (о котором вы узнали в предыдущей главе), чтобы отложить рендеринг частей вашего приложения до выполнения определённого условия (например, загрузки данных).

Фолбэк Suspense встраивается в начальный HTML-файл вместе со статичным контентом. Во время сборки (или при ревалидации) статичный контент предварительно рендерится, создавая статичную оболочку. Рендеринг динамического контента откладывается до запроса маршрута пользователем.

Обёртывание компонента в Suspense не делает сам компонент динамическим, а скорее служит границей между статичным и динамическим кодом.

Давайте посмотрим, как можно реализовать PPR в вашем маршруте дашборда.

Реализация частичного предварительного рендеринга

Включите PPR в вашем Next.js-приложении, добавив опцию ppr в файл next.config.ts:

next.config.ts
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  experimental: {
    ppr: 'incremental'
  }
};
 
export default nextConfig;

Значение 'incremental' позволяет внедрять PPR для конкретных маршрутов.

Затем добавьте опцию конфигурации сегмента experimental_ppr в ваш лейаут дашборда:

/app/dashboard/layout.tsx
import SideNav from '@/app/ui/dashboard/sidenav';
 
export const experimental_ppr = true;
 
// ...

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

Преимущество частичного предварительного рендеринга в том, что вам не нужно изменять код для его использования. Достаточно обернуть динамические части вашего маршрута в Suspense, и Next.js поймёт, какие части маршрута статичны, а какие — динамичны.

Мы считаем, что PPR имеет потенциал стать стандартной моделью рендеринга для веб-приложений, объединяя лучшее от статических сайтов и динамического рендеринга. Однако он всё ещё экспериментален. Мы надеемся стабилизировать его в будущем и сделать стандартным способом разработки с Next.js.

Теперь вы можете отменить эти изменения и перейти к следующей главе.

Итоги

Подведём итоги: вы сделали несколько вещей для оптимизации загрузки данных в вашем приложении:

  1. Создали базу данных в том же регионе, что и код приложения, чтобы уменьшить задержку между сервером и базой данных.
  2. Загружали данные на сервере с помощью React Server Components. Это позволяет оставить дорогостоящие запросы данных и логику на сервере, уменьшить клиентский JavaScript-бандл и предотвратить раскрытие секретов базы данных клиенту.
  3. Использовали SQL для загрузки только необходимых данных, уменьшая объём передаваемых данных для каждого запроса и количество JavaScript, необходимого для преобразования данных в памяти.
  4. Параллелизировали загрузку данных с помощью JavaScript — там, где это было уместно.
  5. Реализовали потоковую передачу, чтобы медленные запросы данных не блокировали всю страницу, и пользователь мог начать взаимодействовать с интерфейсом, не дожидаясь полной загрузки.
  6. Перенесли загрузку данных в компоненты, которым они нужны, изолировав таким образом динамические части маршрутов.

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