Next.js: Эволюция архитектуры, App Router и стратегии рендеринга

Углубленный курс по переходу от Pages Router к App Router, охватывающий Server Components, Server Actions, механизмы гидратации и влияние различных стратегий рендеринга на SEO.

1. Сравнение архитектур: Pages Router против App Router и новые возможности маршрутизации

Сравнение архитектур: Pages Router против App Router и новые возможности маршрутизации

Добро пожаловать на курс по Next.js. Мы начинаем наше погружение с фундаментального сдвига, который произошел в экосистеме React и Next.js за последние годы. Если вы работали с Next.js до 13-й версии, вы привыкли к определенному укладу вещей. Однако с появлением App Router правила игры изменились, превратив Next.js из простого мета-фреймворка в полноценное решение для построения архитектуры веб-приложений.

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

Pages Router: Эпоха монолитного клиента

Долгое время стандартом в Next.js был Pages Router. Его архитектура строилась вокруг папки pages. Любой файл, созданный в этой директории, автоматически становился маршрутом (роутом) приложения. Например, файл pages/about.js становился доступен по адресу /about.

Особенности Pages Router

В этой модели мы использовали специальные функции для получения данных:

* getStaticProps — для статической генерации (SSG). * getServerSideProps — для рендеринга на сервере при каждом запросе (SSR). * getStaticPaths — для генерации динамических маршрутов.

Главная проблема этой архитектуры заключалась в отсутствии встроенной поддержки вложенных макетов (nested layouts). Чтобы сохранить состояние боковой панели или плеера при переходе между страницами, разработчикам приходилось использовать сложные обходные пути в файле _app.js.

Кроме того, в Pages Router по умолчанию все компоненты в дереве рендеринга гидратировались на клиенте. Даже если компонент просто отображал статический текст, его JavaScript-код отправлялся в браузер, увеличивая размер бандла (Total Blocking Time).

App Router: Смена парадигмы

App Router — это новая модель, представленная в Next.js 13.4 (как стабильная), работающая в директории app. Это не просто изменение названия папки, это полная переработка того, как React работает с сервером и клиентом.

Ключевые отличия:

  • Server Components по умолчанию. Все компоненты в папке app являются серверными (React Server Components — RSC), если вы явно не укажете обратное.
  • Вложенные макеты (Nested Layouts). Файлы layout.js позволяют оборачивать страницы и сохранять состояние UI при навигации.
  • Специальные файлы. Роутинг теперь определяется папками, а не файлами. Внутри папки маршрута используются зарезервированные имена файлов: page.js, layout.js, loading.js, error.js, not-found.js.
  • !Сравнение файловой структуры: плоская структура Pages Router против вложенной структуры App Router

    Server Components против Client Components

    Понимание различия между серверными и клиентскими компонентами — это фундамент работы с App Router.

    Server Components (RSC)

    В App Router компоненты рендерятся на сервере. Результат их работы — это не HTML-строка (как в классическом SSR), и не DOM-элементы, а специальный формат данных (RSC Payload), который React использует для построения дерева компонентов.

    Плюсы Server Components:

    * Нулевой размер бандла: Код серверного компонента и его зависимости (например, библиотека для форматирования даты) не отправляются в браузер. * Прямой доступ к бэкенду: Вы можете обращаться к базе данных или файловой системе прямо внутри компонента. * Безопасность: Секретные ключи API и токены остаются на сервере. * Улучшенное SEO: Сервер отдает готовый контент, который легко индексируется поисковыми роботами.

    Минусы:

    * Нет доступа к Browser API (window, localStorage). * Нельзя использовать хуки (useState, useEffect). * Нельзя вешать обработчики событий (onClick).

    Client Components

    Чтобы добавить интерактивность (клики, состояние, эффекты), мы используем директиву 'use client' в начале файла. Это сообщает Next.js, что данный компонент и все его дочерние элементы должны быть отправлены в браузер и пройти процесс гидратации.

    #### Процесс рендеринга Client Component (на примере счетчика)

    Рассмотрим компонент <Counter /> с директивой 'use client'. Процесс его появления на экране выглядит так:

  • Серверный пре-рендер: Сервер выполняет компонент и генерирует начальный HTML. Это важно: даже клиентские компоненты сначала рендерятся в HTML на сервере для SEO и скорости первой отрисовки (FCP).
  • Отдача HTML: Браузер получает HTML и показывает пользователю статичную картинку счетчика (число 0).
  • Загрузка JS: Браузер загружает JavaScript-бандл для этого компонента.
  • Hydration (Гидратация): React «оживляет» HTML, привязывая к нему обработчики событий и инициализируя состояние.
  • Интерактивность: Теперь при нажатии кнопки счетчик обновляется. Все дальнейшие изменения происходят только на клиенте.
  • !Жизненный цикл клиентского компонента: от серверного HTML до интерактивности

    Стратегии рендеринга в App Router

    App Router отказывается от явных функций типа getServerSideProps в пользу гибридного подхода, основанного на Fetch API и конфигурации кэширования.

    1. Static Rendering (SSG) — По умолчанию

    Если компонент не использует динамические функции (куки, заголовки) и данные кэшируются, Next.js генерирует HTML во время сборки (build time). Этот HTML переиспользуется для каждого запроса.

    2. Dynamic Rendering (SSR)

    Рендеринг происходит для каждого пользователя в момент запроса. Это включается автоматически, если:

    * Вы используете динамические функции: cookies(), headers(). * Вы отключаете кэш в запросе данных: fetch(url, { cache: 'no-store' }).

    3. Incremental Static Regeneration (ISR)

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

    Пример:

    4. Streaming

    Технология, позволяющая разбивать UI на части и отправлять их клиенту по мере готовности. Используя компонент <Suspense>, вы можете мгновенно показать скелетон или спиннер, пока тяжелая часть страницы (например, список товаров) еще грузится на сервере.

    5. Client-Side Rendering (CSR)

    Классический подход React SPA. Используется внутри компонентов с 'use client', когда данные загружаются через useEffect или библиотеки вроде SWR/TanStack Query уже после загрузки страницы.

    6. Partial Prerendering (PPR) — Экспериментально

    Новейшая стратегия, объединяющая статику и динамику. Статическая оболочка (shell) отдается мгновенно (как SSG), а динамические части (дырки в статике) стримятся параллельно. Это «Святой Грааль» веб-производительности.

    Server Actions: Мутации данных

    В Pages Router для отправки формы нам нужно было создавать API Route (pages/api/form.js) и вызывать его через fetch на клиенте. App Router вводит Server Actions.

    Это асинхронные функции с директивой 'use server', которые можно вызывать прямо из компонентов (даже клиентских) или форм.

    Как это работает:

  • Вы пишете функцию, которая обращается к БД.
  • Передаете эту функцию в проп action формы.
  • При отправке формы Next.js автоматически делает POST-запрос к серверу, выполняет функцию и возвращает результат.
  • Это убирает необходимость вручную писать API-эндпоинты для простых мутаций.

    Влияние на SEO

    Переход на App Router значительно улучшает SEO-показатели:

    * Server HTML: Весь контент серверных компонентов (и начальное состояние клиентских) доступен в исходном коде страницы. * Metadata API: Вместо тега <Head>, теперь мы экспортируем объект metadata из layout.js или page.js, что упрощает управление мета-тегами, Open Graph и JSON-LD. * Скорость: Меньше JavaScript на клиенте означает более быструю загрузку и лучшие показатели Core Web Vitals, что является фактором ранжирования Google.

    > «App Router — это не просто обновление, это взросление React как фуллстек-технологии, где граница между клиентом и сервером становится инструментом, а не препятствием.»

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

    2. Server Components и Server Actions: преимущества, недостатки и безопасная работа с данными

    Server Components и Server Actions: преимущества, недостатки и безопасная работа с данными

    В предыдущей статье мы рассмотрели фундаментальные различия между Pages Router и App Router, а также познакомились с концепцией рендеринга. Теперь пришло время углубиться в две технологии, которые делают App Router по-настоящему мощным инструментом: React Server Components (RSC) и Server Actions.

    Эти технологии меняют не только способ написания кода, но и ментальную модель разработчика. Мы переходим от создания API-эндпоинтов для каждого чиха к вызову серверных функций прямо из UI, и от отправки мегабайтов JavaScript к умному разделению ответственности между клиентом и сервером.

    React Server Components (RSC): Глубокое погружение

    Как мы уже знаем, в директории app все компоненты по умолчанию являются серверными. Это означает, что они исполняются исключительно на сервере Node.js (или в Edge Runtime) и никогда не попадают в браузер в виде JavaScript-кода.

    Архитектурные преимущества

  • Нулевой размер бандла (Zero Bundle Size)
  • Это, пожалуй, самое очевидное преимущество. Представьте, что вам нужно отрендерить Markdown-текст в HTML. Для этого вы используете тяжелую библиотеку. В случае с Client Components (или Pages Router) код этой библиотеки был бы упакован и отправлен пользователю.

    С Server Components библиотека импортируется, выполняется на сервере, генерирует результат (UI), и только этот результат отправляется клиенту. Сама библиотека остается на сервере.

  • Прямой доступ к бэкенду
  • Поскольку код выполняется на сервере, вы можете напрямую обращаться к базе данных, файловой системе или внутренним микросервисам без необходимости создавать промежуточный API-слой.

  • Автоматическое разделение кода (Automatic Code Splitting)
  • В Pages Router нам приходилось использовать next/dynamic для ленивой загрузки компонентов. В App Router серверные компоненты автоматически разбивают код. Клиентские компоненты, импортируемые в серверные, также автоматически становятся точками разделения кода.

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

    Ограничения и правила работы

    Работа с RSC накладывает строгие ограничения, которые необходимо учитывать при проектировании:

    * Отсутствие интерактивности: Вы не можете использовать onClick, onChange и другие обработчики событий. * Отсутствие хуков: useState, useEffect, useReducer и пользовательские хуки недоступны. * Нет доступа к Browser API: window, document, localStorage не существуют в среде выполнения сервера.

    Проблема сериализации (Serialization Boundary)

    Когда вы передаете пропсы от Server Component к Client Component, эти данные должны пройти через «сетевой мост». Это означает, что пропсы должны быть сериализуемыми.

    Что можно передавать: * Строки, числа, булевы значения. * Массивы и простые объекты. * null и undefined.

    Что нельзя передавать: * Функции (кроме Server Actions). * Классы. * Экземпляры Date (их нужно преобразовать в строку).

    Паттерн композиции: «Листья» интерактивности

    Чтобы сохранить преимущества RSC и при этом добавить интерактивность, используется паттерн вынесения клиентской логики в «листья» дерева компонентов.

    Вместо того чтобы делать всю страницу клиентской ('use client'), вы делаете клиентским только тот маленький компонент, которому это действительно нужно (например, кнопку или поле ввода).

    Пример правильной архитектуры:

    Server Actions: Эволюция мутаций

    До появления Server Actions для обработки отправки формы или нажатия кнопки, требующей изменения данных на сервере, нам приходилось:

  • Создавать API Route (pages/api/...).
  • Писать fetch запрос на клиенте.
  • Обрабатывать состояния загрузки и ошибок.
  • Server Actions — это функции, которые выполняются на сервере, но могут быть вызваны с клиента. Они работают как удаленный вызов процедур (RPC).

    Создание Server Action

    Чтобы объявить серверное действие, используется директива 'use server'. Ее можно разместить в начале асинхронной функции (внутри серверного компонента) или в начале отдельного файла.

    Использование в формах

    Next.js расширяет стандартный HTML-атрибут action для поддержки Server Actions. Это позволяет форме работать даже без JavaScript (прогрессивное улучшение).

    !Схема работы Server Action: от клика пользователя до выполнения функции на сервере

    Безопасность в Server Actions

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

    Любая функция с 'use server' может быть вызвана злоумышленником напрямую, минуя ваш UI. Поэтому к ним нужно относиться так же строго, как к REST API эндпоинтам.

    1. Аутентификация и Авторизация

    Никогда не полагайтесь на то, что действие вызвано из «защищенной» страницы. Всегда проверяйте права пользователя внутри самого действия.

    2. Валидация входных данных

    Данные, приходящие в Server Action (через FormData или аргументы), могут быть подделаны. Всегда используйте библиотеки валидации, такие как Zod.

    3. Защита от CSRF

    Хорошая новость: Next.js автоматически защищает Server Actions от CSRF-атак, проверяя заголовки Origin и Host. Вам не нужно вручную добавлять токены CSRF, как это делалось в старых фреймворках.

    Секреты и переменные окружения

    Server Components и Server Actions имеют доступ к переменным окружения, которые не начинаются с NEXT_PUBLIC_. Это позволяет безопасно использовать приватные ключи API (например, STRIPE_SECRET_KEY) прямо в коде компонента или действия.

    > «Правило большого пальца: если код выполняется на сервере, секреты в безопасности. Если код отправляется клиенту, секреты утекли.»

    Чтобы предотвратить случайную утечку серверного кода в клиентский бандл, рекомендуется использовать пакет server-only.

    Заключение

    Переход на Server Components и Server Actions — это шаг к более эффективной и безопасной веб-разработке. Мы получаем производительность статики с гибкостью динамики, а также упрощаем работу с данными, убирая лишние слои абстракции.

    Однако эта мощь требует ответственности. Понимание того, где заканчивается сервер и начинается клиент, а также строгое соблюдение правил безопасности при написании Server Actions — это ключевые навыки современного Next.js разработчика.

    В следующей статье мы разберем вложенные макеты (Nested Layouts) и то, как правильно организовать навигацию и состояние UI в сложных приложениях.

    3. Методы рендеринга в App Router: Static, Dynamic, ISR, Streaming и PPR

    Методы рендеринга в App Router: Static, Dynamic, ISR, Streaming и PPR

    Мы продолжаем наш путь по изучению архитектуры Next.js. В прошлых статьях мы разобрали, из чего состоит приложение (Server и Client Components) и как мы можем изменять данные (Server Actions). Теперь пришло время ответить на вопрос: как и когда эти компоненты превращаются в HTML, который видит пользователь.

    В App Router стратегия рендеринга больше не определяется на уровне страницы (как это было с getServerSideProps), а выводится автоматически на основе того, какие API и методы получения данных вы используете. Это делает систему более гибкой, но требует понимания внутренних механизмов.

    1. Static Rendering (SSG) — Стратегия по умолчанию

    В Next.js App Router действует правило: всё является статическим, пока не доказано обратное. Если ваш компонент не использует динамические функции (например, чтение куки) и не отключает кэширование данных, Next.js сгенерирует HTML для этого маршрута один раз во время сборки (build time).

    Этот HTML сохраняется в CDN и отдается каждому пользователю мгновенно. Это самый быстрый способ доставки контента.

    Когда использовать?

    * Маркетинговые страницы (Landing pages). * Статьи в блоге. * Документация. * Списки товаров, которые редко меняются.

    Пример запроса данных для статики:

    2. Dynamic Rendering (SSR)

    Динамический рендеринг происходит в момент запроса (request time). Это означает, что для каждого пользователя сервер заново генерирует HTML. В App Router это происходит автоматически, если:

  • Вы используете динамические функции: cookies(), headers(), searchParams.
  • Вы явно отключаете кэширование в запросах данных.
  • Когда использовать?

    * Персонализированные дашборды. * Ленты новостей в реальном времени. * Страницы, зависящие от параметров URL или геолокации пользователя.

    Пример переключения в динамический режим:

    Также можно принудительно сделать страницу динамической через переменную конфигурации:

    3. Incremental Static Regeneration (ISR)

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

    Например, если вы установите интервал в 60 секунд:

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

    4. Streaming (Потоковая передача)

    Традиционный SSR имеет проблему «водопада»: сервер должен загрузить все данные, затем сгенерировать весь HTML, и только потом отправить его браузеру. Пользователь видит белый экран, пока сервер работает.

    Streaming позволяет разбить HTML страницы на части (chunks) и отправлять их клиенту по мере готовности.

    В App Router это реализуется через компонент <Suspense> из React. Вы оборачиваете асинхронный компонент, который долго грузит данные, в Suspense, и показываете запасной UI (fallback).

    !Визуализация того, как Streaming позволяет пользователю видеть часть интерфейса до того, как загрузится вся страница.

    5. Partial Prerendering (PPR) — Экспериментально

    Это новейшая стратегия, которая объединяет лучшее из миров SSG и Streaming. Идея заключается в том, что страница имеет статическую оболочку (Shell), которая генерируется при сборке, и динамические дырки, которые заполняются асинхронно.

    В отличие от обычного Streaming, где начальный HTML формируется в момент запроса, в PPR статическая часть (шапка, футер, навигация) отдается мгновенно из CDN (как статика), а динамическая часть стримится параллельно.

    Глубокое погружение: Рендеринг Client Components

    Существует распространенное заблуждение, что компоненты с директивой 'use client' рендерятся только в браузере. Это не так. Давайте разберем жизненный цикл клиентского компонента, например, интерактивного счетчика.

    Этапы появления Client Component на экране:

  • Серверный пре-рендер (Pre-rendering):
  • Даже если компонент помечен как 'use client', Next.js выполняет его на сервере, чтобы получить начальный HTML. На этом этапе useState инициализируется значением по умолчанию, а useEffect не запускается. Это нужно для того, чтобы пользователь сразу увидел контент (First Contentful Paint) и для SEO.

  • Отправка HTML:
  • Браузер получает готовую HTML-разметку. Пользователь видит кнопку и цифру «0», но нажать на неё пока нельзя — это просто «мертвая» картинка.

  • Загрузка JavaScript (RSC Payload + JS Bundle):
  • Браузер загружает код React и код вашего компонента.

  • Hydration (Гидратация):
  • React сопоставляет загруженный JavaScript с уже существующим HTML в DOM. Он «прикрепляет» обработчики событий (event listeners) к кнопкам и инициализирует состояние.

  • Интерактивность:
  • Только после гидратации компонент становится полностью функциональным. Теперь работают onClick, useEffect и перерендеры при изменении стейта.

    !Жизненный цикл клиентского компонента: от статического HTML до интерактивного приложения.

    Влияние на SEO

    Переход на App Router и новые стратегии рендеринга оказывают прямое влияние на поисковую оптимизацию:

    * Server HTML индексируется идеально. Поскольку и Server Components, и начальное состояние Client Components отдаются в виде HTML, поисковые роботы видят контент сразу. Им не нужно выполнять JavaScript, чтобы прочитать текст на странице. * Streaming улучшает Core Web Vitals. Быстрый ответ сервера (TTFB) и быстрая отрисовка контента (FCP) — это факторы ранжирования Google. * Metadata API. В App Router управление мета-тегами (title, description, open graph) стало программным и серверным. Вы можете генерировать мета-теги динамически на основе данных из БД, и они гарантированно попадут в HTML.

    > «Важно помнить: контент, который подгружается на клиенте (CSR) через useEffect уже после гидратации, может индексироваться хуже или с задержкой, так как требует от робота выполнения JS.»

    Итоговое сравнение: Server Components vs Client Components

    Чтобы закрепить материал курса, давайте структурируем плюсы и минусы использования Server Components (RSC).

    Server Components (RSC)

    Плюсы: * Меньше JavaScript: Код компонента не летит в браузер. Это критически важно для пользователей с медленным интернетом. * Безопасность: Можно хранить токены и ключи API прямо в коде, они не утекут на клиент. * Доступ к ресурсам: Прямое подключение к БД или файловой системе. * SEO: Отдают готовый HTML.

    Минусы: * Нет интерактивности: Нельзя использовать onClick, onChange. * Нет состояния: useState и useReducer недоступны. * Нет Browser API: Нет доступа к window, localStorage, navigator.

    Server Actions

    Это «клей», который соединяет клиент и сервер в новой архитектуре.

    * Функции с директивой 'use server' выполняются только на сервере. * Они используются для мутаций данных (отправка форм, нажатие кнопок «лайк», «купить»). * Они могут быть вызваны из Client Components, работая как безопасный мост к бэкенду.

    Заключение

    App Router предоставляет богатый набор инструментов для оптимизации производительности. Вы больше не обязаны выбирать одну стратегию для всего сайта. Главная страница может быть статической (SSG) для скорости, личный кабинет — динамическим (SSR) для актуальности, а лента новостей — использовать Streaming для лучшего UX.

    Понимание того, как работает гидратация и чем она отличается от простого рендеринга, поможет вам избегать ошибок, связанных с рассинхронизацией UI (Hydration Mismatch), и создавать приложения, которые нравятся и пользователям, и поисковым системам.

    4. Client Components: механика use client, процесс гидратации и жизненный цикл состояния

    Client Components: механика use client, процесс гидратации и жизненный цикл состояния

    В предыдущих модулях мы подробно разобрали революцию Server Components. Мы узнали, как они позволяют нам исполнять код на сервере, обращаться к базам данных напрямую и уменьшать размер JavaScript-бандла. Однако веб — это не только статическая доставка контента. Это интерактивность: формы, кнопки, анимации, модальные окна и сложные интерфейсы.

    Именно здесь на сцену выходят Client Components. В App Router они не являются «старым способом делать вещи», а представляют собой специализированный инструмент для создания интерактивного UI. В этой статье мы развеем главные мифы о клиентских компонентах, разберем их жизненный цикл по секундам и поймем, как именно React «оживляет» статический HTML.

    Директива "use client": Граница миров

    Самое важное, что нужно понять: директива 'use client' — это не переключатель «выполнить этот код в браузере». Это сетевая граница (Network Boundary).

    Когда Next.js встречает эту директиву в начале файла, он понимает: «Всё, что находится в этом файле, и всё, что этот файл импортирует, является частью клиентского бандла». Это точка входа в клиентскую часть вашего приложения.

    Как это работает на практике

    Представьте ваше приложение как дерево компонентов. Корнем всегда является Server Component (обычно layout.js или page.js). Ветви могут оставаться серверными, пока вы явно не объявите границу.

    В этом примере ClientCounter и все его зависимости (включая сам React) будут упакованы и отправлены в браузер. Но Page останется на сервере.

    !Визуализация границы между серверными и клиентскими компонентами в дереве приложения

    Великий миф: «Client Components рендерятся только в браузере»

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

    > Client Components выполняются на сервере.

    Да, вы не ослышались. Чтобы обеспечить быструю первую отрисовку (First Contentful Paint) и SEO, Next.js выполняет пре-рендер (pre-render) клиентских компонентов на сервере.

    Процесс рендеринга по шагам

    Давайте проследим путь клиентского компонента от сервера до клика пользователя.

    #### 1. Серверный этап (Pre-rendering) Когда поступает запрос на страницу, Next.js рендерит всё дерево компонентов на сервере. В этот момент: * Server Components выполняются полностью. * Client Components также выполняются, но без интерактивности. React просто вызывает функцию компонента, чтобы получить начальный HTML. * Хуки useState инициализируются начальным значением. * Хуки useEffect не запускаются. * Обработчики событий (onClick) игнорируются.

    Результат: Сервер генерирует полный HTML-документ, где на месте вашего счетчика уже стоит цифра 0.

    #### 2. Доставка HTML Браузер получает HTML. Пользователь видит страницу мгновенно. Он видит кнопку и счетчик. Но если он нажмет на кнопку прямо сейчас — ничего не произойдет. Страница выглядит живой, но она «мертва».

    #### 3. Загрузка JavaScript Параллельно браузер загружает JavaScript-бандл (RSC Payload + код клиентских компонентов).

    #### 4. Гидратация (Hydration) Это магический момент. React запускается в браузере, берет загруженный JS-код и сопоставляет его с уже существующим HTML в DOM.

    React не перерисовывает HTML заново (это было бы медленно). Вместо этого он проходит по DOM-дереву и «развешивает» слушатели событий (event listeners) на нужные элементы. Он как бы вливает воду (гидратирует) в сухую губку HTML, делая её мягкой и интерактивной.

    #### 5. Интерактивность Только после завершения гидратации начинают работать useEffect, подписки на события и изменения стейта.

    !Этапы жизненного цикла: от серверного HTML до интерактивного приложения

    Опасности гидратации: Hydration Mismatch

    Поскольку компонент рендерится дважды (один раз на сервере для HTML, второй раз в браузере для гидратации), результат этих двух рендеров обязан совпадать.

    Если HTML, который пришел с сервера, отличается от того, что React сгенерировал на клиенте при первом проходе, возникнет ошибка: Hydration Mismatch.

    Типичный пример ошибки

    React увидит, что в серверном HTML написано 12:00:01, а клиентский код сгенерировал 12:00:02. Он выбросит предупреждение и перерисует кусок интерфейса, что ударит по производительности.

    Как исправить?

    Используйте useEffect, чтобы установить значение, зависящее от браузера, уже после гидратации.

    Client Components и SEO

    Существует миф, что использование 'use client' убивает SEO, превращая приложение в SPA (Single Page Application), которое поисковики не видят. Это неверно в контексте Next.js App Router.

    Как мы выяснили выше, Client Components проходят серверный пре-рендер. Поисковый робот (Googlebot, Yandex) получает полноценный HTML с контентом вашего компонента.

    Что индексируется:

  • Начальное состояние (Initial State): Текст, заголовки, списки, которые видны сразу при загрузке.
  • Пропсы: Данные, переданные с сервера в клиентский компонент.
  • Что НЕ индексируется (или индексируется хуже):

  • Контент, загружаемый через useEffect: Если ваш компонент рендерит спиннер, а потом делает fetch на клиенте, робот увидит только спиннер.
  • Состояние после взаимодействия: Если текст появляется только после клика на кнопку, робот его, скорее всего, не увидит.
  • Стратегия: Используйте Server Components для получения данных и формирования основного контента страницы, а Client Components — только для интерактивных элементов (кнопки, фильтры, поиск).

    Сравнение: Когда использовать Client Components?

    Чтобы закрепить материал, давайте четко разграничим зоны ответственности.

    Используйте Client Components, когда:

    * Нужны интерактивные события (onClick, onChange, onSubmit). * Нужны хуки состояния и эффектов (useState, useEffect, useReducer). * Нужен доступ к API браузера (localStorage, window, navigator, geolocation). * Вы используете классовые компоненты (хотя лучше переходить на функциональные).

    Оставляйте Server Components (по умолчанию), когда:

    * Нужно получить данные из БД или API. * Нужен доступ к бэкенд-ресурсам (файловая система, секретные ключи). * Компонент просто отображает контент и не требует взаимодействия. * Важен минимальный размер JS-бандла.

    Паттерн "Листья дерева"

    Для максимальной производительности старайтесь спускать директиву 'use client' как можно ниже по дереву компонентов. Не делайте корневой layout.js клиентским только потому, что вам нужен контекст темы.

    Вместо этого оберните провайдер контекста в отдельный клиентский компонент и импортируйте его в серверный лейаут.

    Таким образом, всё ваше приложение остается серверным, и только логика темы отправляется в браузер.

    Заключение

    Client Components в Next.js — это мощный инструмент, который возвращает нам привычный React, но встраивает его в современную серверную архитектуру. Понимание того, что они рендерятся и на сервере (для HTML), и на клиенте (для интерактивности), является ключом к созданию быстрых приложений без ошибок гидратации.

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

    5. SEO в Next.js: индексация серверного и клиентского контента и управление метаданными

    SEO в Next.js: индексация серверного и клиентского контента и управление метаданными

    Добро пожаловать обратно. В предыдущих модулях мы проделали большой путь: от понимания архитектурных сдвигов в App Router до тонкостей гидратации клиентских компонентов. Мы научились рендерить приложения эффективно. Но какой толк от самого быстрого и технологичного сайта, если его никто не может найти?

    В этой статье мы разберем, как поисковые системы (Google, Yandex, Bing) видят ваше Next.js приложение. Мы развеем мифы о том, что use client вредит продвижению, научимся управлять мета-тегами с помощью нового Metadata API и настроим технический SEO для идеальной индексации.

    Как поисковые роботы видят ваш сайт

    В эпоху ранних SPA (Single Page Applications) на чистом React, SEO было главной головной болью. При заходе на сайт робот видел пустой div с id="root" и скрипт. Чтобы увидеть контент, роботу нужно было выполнить JavaScript. Google научился это делать достаточно хорошо, но другие поисковики и социальные сети (при шеринге ссылок) часто пасовали.

    Next.js решает эту проблему фундаментально, отдавая готовый HTML с сервера. Однако в App Router у нас есть два типа компонентов, и важно понимать, как индексируется каждый из них.

    1. Индексация Server Components (RSC)

    Здесь всё просто и идеально. Поскольку серверные компоненты исполняются на сервере и превращаются в специальный формат данных, который затем трансформируется в HTML, поисковый робот получает контент в чистом виде.

    Если вы загружаете список товаров в серверном компоненте:

    Робот увидит в исходном коде страницы полный список <li> с названиями товаров. Это золотой стандарт SEO.

    2. Индексация Client Components

    В прошлой статье мы выяснили, что компоненты с директивой 'use client' проходят процесс серверного пре-рендера. Это критически важно для SEO.

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

    Что индексируется: * Весь текст и структура, которые видны при первой загрузке. * Значения пропсов, переданных с сервера. * Начальное состояние useState.

    Что НЕ индексируется (или индексируется с трудом): * Контент, который появляется только после взаимодействия (например, текст внутри закрытой вкладки, если он не был в DOM). * Данные, загружаемые на клиенте (CSR).

    !Визуализация различий в исходном коде страницы для разных стратегий загрузки данных

    Ловушка useEffect: Где теряется SEO

    Самая частая ошибка при переходе на Next.js — использование привычных паттернов React SPA для загрузки данных, важных для SEO.

    Рассмотрим плохой пример:

    Robots.txt

    Аналогично, файл app/robots.txt.js (или просто app/robots.js) управляет доступом роботов.

    JSON-LD: Структурированные данные

    Чтобы получить расширенные сниппеты в Google (звездочки рейтинга, цена товара, рецепты), нужно использовать JSON-LD. В Next.js это делается путем вставки тега <script> с данными в компонент.

    Заключение

    Next.js App Router предоставляет мощнейший инструментарий для SEO, который ранее требовал сложной настройки. Главное, что нужно запомнить:

  • Server Components — ваши лучшие друзья для основного контента.
  • Client Components индексируются отлично, если данные переданы в них через пропсы, а не загружаются внутри useEffect.
  • Metadata API позволяет гибко управлять тегами <head> и социальными превью.
  • Используйте специальные файлы sitemap.js и robots.js для автоматизации технического SEO.
  • Правильно используя эти инструменты, вы обеспечите своему приложению не только высокую производительность, но и отличную видимость в поисковой выдаче.

    В следующем модуле мы перейдем к вопросам деплоя и оптимизации производительности (Core Web Vitals), чтобы закрепить успех нашего приложения в реальном мире.