Рендеринг
Рендеринг преобразует написанный вами код в пользовательские интерфейсы. React и Next.js позволяют создавать гибридные веб-приложения, где части кода могут рендериться на сервере или клиенте. Этот раздел поможет понять различия между этими средами рендеринга, стратегиями и средами выполнения.
Основы
Для начала полезно ознакомиться с тремя фундаментальными концепциями веба:
- Среды выполнения, в которых может выполняться код вашего приложения: сервер и клиент.
- Жизненный цикл запроса-ответа, который инициируется при посещении или взаимодействии пользователя с приложением.
- Сетевая граница, разделяющая серверный и клиентский код.
Среды рендеринга
Существует две среды, в которых могут рендериться веб-приложения: клиент и сервер.

- Клиент — это браузер на устройстве пользователя, который отправляет запрос серверу для получения кода приложения, а затем преобразует ответ сервера в пользовательский интерфейс.
- Сервер — это компьютер в дата-центре, который хранит код вашего приложения, получает запросы от клиента и отправляет соответствующий ответ.
Исторически разработчикам приходилось использовать разные языки (например, JavaScript, PHP) и фреймворки для написания серверного и клиентского кода. С React разработчики могут использовать один язык (JavaScript) и один фреймворк (например, Next.js или другой на выбор). Эта гибкость позволяет писать код для обеих сред без переключения контекста.
Однако каждая среда имеет свои возможности и ограничения. Поэтому код для сервера и клиента не всегда одинаков. Некоторые операции (например, получение данных или управление состоянием пользователя) лучше подходят для одной среды, чем для другой.
Понимание этих различий ключевое для эффективного использования React и Next.js. Подробнее о различиях и случаях использования мы расскажем на страницах Серверных и Клиентских компонентов, а пока продолжим строить нашу основу.
Жизненный цикл запроса-ответа
В целом все веб-сайты следуют одному жизненному циклу запроса-ответа:
- Действие пользователя: Пользователь взаимодействует с веб-приложением. Это может быть клик по ссылке, отправка формы или ввод URL в адресную строку браузера.
- HTTP-запрос: Клиент отправляет HTTP-запрос на сервер, содержащий информацию о запрашиваемых ресурсах, используемом методе (например,
GET
,POST
) и дополнительные данные при необходимости. - Сервер: Сервер обрабатывает запрос и отвечает соответствующими ресурсами. Этот процесс может включать несколько шагов, таких как маршрутизация, получение данных и т.д.
- HTTP-ответ: После обработки запроса сервер отправляет HTTP-ответ клиенту. Ответ содержит код состояния (указывающий на успешность запроса) и запрошенные ресурсы (например, HTML, CSS, JavaScript, статические файлы и т.д.).
- Клиент: Клиент обрабатывает ресурсы для рендеринга пользовательского интерфейса.
- Действие пользователя: После рендеринга интерфейса пользователь может взаимодействовать с ним, и цикл начинается заново.
Важная часть создания гибридного веб-приложения — решение о том, как разделить работу в этом цикле и где разместить сетевую границу.
Сетевая граница
В веб-разработке сетевая граница — это концептуальная линия, разделяющая разные среды. Например, клиент и сервер или сервер и хранилище данных.
В React вы можете выбрать, где разместить клиент-серверную границу, где это наиболее логично.
За кулисами работа разделяется на две части: граф клиентских модулей и граф серверных модулей. Граф серверных модулей содержит все компоненты, рендерящиеся на сервере, а граф клиентских модулей — все компоненты, рендерящиеся на клиенте.
Можно представить графы модулей как визуальное представление зависимостей между файлами в вашем приложении.
Вы можете использовать директиву React "use client"
для определения границы. Также есть директива "use server"
, которая указывает React выполнять некоторые вычисления на сервере при работе на клиенте.
Создание гибридных приложений
При работе с этими средами полезно представлять поток кода в приложении как однонаправленный. Другими словами, во время ответа код вашего приложения течёт в одном направлении: от сервера к клиенту.
Если вам нужно обратиться к серверу с клиента, вы отправляете новый запрос на сервер, а не повторно используете тот же запрос. Это упрощает понимание того, где рендерить компоненты и где размещать сетевую границу.
На практике такая модель побуждает разработчиков сначала думать о том, что нужно выполнить на сервере, прежде чем отправлять результат клиенту и делать приложение интерактивным.
Эта концепция станет понятнее, когда мы рассмотрим, как можно перемежать клиентские и серверные компоненты в одном дереве компонентов.