JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Принципы работы App Router, рендеринг на сервере и клиент...

Принципы работы App Router, рендеринг на сервере и клиенте (Next.js 15)

Модуль 4: Node.js, Next.js и Angular
7 уровень , 4 лекция
Открыта

1. Суть работы App Router

App Router — это новая система маршрутизации в Next.js, которая полностью строится на структуре папки app/. Каждый подкаталог внутри app/ становится маршрутом, а файлы вроде page.tsx и layout.tsx определяют, что именно будет показано пользователю.

"Маршруты = папки и файлы"

  • /app/page.tsx/ (главная страница)
  • /app/about/page.tsx/about
  • /app/blog/[slug]/page.tsx/blog/что-угодно

Next.js сканирует папку app/ и строит дерево маршрутов. Каждый маршрут может иметь свою разметку (layout.tsx), шаблон (template.tsx), страницу (page.tsx), обработчики ошибок, загрузки и т.д.

App Router — это не просто навигация

App Router — это не только про "куда перейти". Это про то, как и где будет рендериться ваш компонент: на сервере, на клиенте или и там, и там. В эпоху Next.js 15 это становится особенно важным, ведь теперь можно комбинировать серверные и клиентские компоненты, а значит, управлять производительностью и интерактивностью на новом уровне.

2. Рендеринг: сервер, клиент и их гибриды

Серверный рендеринг (Server-side rendering, SSR)

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

  • Плюсы:
    • Быстрый первый рендер (особенно для поисковиков и соцсетей).
    • Отлично подходит для SEO.
    • Можно сразу показывать данные, полученные с сервера.
  • Минусы:
    • Интерактивность появляется чуть позже (после "гидратации").
    • Каждый переход между страницами может требовать нового запроса к серверу.

Клиентский рендеринг (Client-side rendering, CSR)

В этом случае сервер отдаёт минимальный HTML и большой JS-бандл. Всё остальное происходит в браузере: React сам собирает виртуальное DOM-дерево, сам запрашивает данные, сам всё рисует.

  • Плюсы:
    • Молниеносная навигация после загрузки первого бандла.
    • Можно делать очень динамичные, "живые" интерфейсы.
  • Минусы:
    • Первый рендер медленнее (особенно на слабых устройствах).
    • SEO работает хуже (поисковик может не увидеть контент).

Гибридный рендеринг (Server + Client)

Next.js позволяет комбинировать оба подхода: часть компонентов рендерится на сервере, часть — только на клиенте. Это позволяет получить лучшее из обоих миров: быстрый первый рендер, хороший SEO, и при этом — интерактивность и динамику на клиенте.

В App Router это реализовано через Server Components и Client Components.

3. Как Next.js решает: где рендерить компонент?

В Next.js 15 по умолчанию все компоненты в папке app/серверные. Это значит, что они рендерятся на сервере, а в браузер отправляется уже готовый HTML. Если компоненту нужна интерактивность (например, обработка клика или состояние), его нужно явно сделать клиентским с помощью директивы "use client".

Серверные компоненты (Server Components)

  • Рендерятся только на сервере.
  • Могут обращаться к базе данных, файлам, секретным API — всему, что есть на сервере.
  • Не могут использовать хуки состояния (useState, useEffect и т.п.).
  • Не могут напрямую реагировать на действия пользователя.

Пример:


// app/about/page.tsx
export default function AboutPage() {
  // Это серверный компонент по умолчанию
  return <h1>О нас</h1>;
}

Клиентские компоненты (Client Components)

  • Рендерятся на клиенте (в браузере).
  • Могут использовать хуки состояния, эффекты, обработчики событий.
  • Объявляются с помощью директивы "use client" в начале файла.

Пример:


// app/components/Counter.tsx
"use client";
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Нажали {count} раз
    </button>
  );
}

Важно! Даже если вы импортируете клиентский компонент в серверный, Next.js "разрулит" это: сервер соберёт HTML, а клиентский компонент подключит интерактивность уже в браузере.

4. Схема работы App Router

Вот как это выглядит в виде схемы (упрощённо):


[Запрос пользователя] 
      |
      v
[Next.js сервер]
      |
      | 1. Собирает дерево маршрутов по app/
      | 2. Рендерит серверные компоненты (SSR)
      | 3. Встраивает клиентские компоненты как "островки"
      v
[Готовый HTML + JS]
      |
      v
[Браузер пользователя]
      |
      | 4. Показывает HTML сразу
      | 5. "Гидратирует" клиентские компоненты (оживляет их)
      v
[Пользователь видит страницу, может взаимодействовать]

Как это выглядит в коде?


// app/page.tsx
import Counter from "./components/Counter";

export default function HomePage() {
  return (
    <main>
      <h1>Главная страница</h1>
      <Counter /> {/* Это клиентский компонент */}
    </main>
  );
}

Пояснение:

  • Всё, кроме <Counter />, рендерится на сервере.
  • <Counter /> — клиентский, поэтому в браузер прилетает его JS-код, и только он может быть интерактивным.

5. Полезные нюансы

Как App Router помогает вашему приложению?

  • SEO и скорость
    Серверный рендеринг означает, что поисковики сразу видят содержимое страницы — это отлично для SEO. Пользователь тоже сразу видит контент, даже если интернет медленный или устройство слабое.
  • Гибкость и масштабируемость
    Вы сами решаете, что рендерить на сервере, а что на клиенте. Например, формы, счетчики, анимации — на клиенте, а статический текст, статьи, каталоги — на сервере.
  • Безопасность
    Серверные компоненты могут обращаться к секретам, API-ключам, базе данных — и всё это не "утечёт" в браузер пользователя.

Как устроена "гидратация"

Гидратация — это процесс, когда Next.js берёт уже готовый HTML (полученный с сервера), "добавляет" к нему JS-код и оживляет клиентские компоненты. Пользователь видит страницу сразу, а интерактивность появляется чуть позже, когда браузер скачает нужный JS.

Зачем это нужно?
Чтобы соединить скорость SSR и интерактивность CSR. Это как если бы вы купили мебель уже собранной (SSR), а потом просто включили свет (CSR).

Как App Router решает, что отдавать серверу, а что клиенту?

  • Если компонент не помечен как "use client", он серверный.
  • Если компоненту нужен useState, useEffect, обработчики событий — он должен быть клиентским.
  • Серверные компоненты могут импортировать клиентские, но не наоборот.
  • Вся цепочка вверх от клиентского компонента становится клиентской (важно для архитектуры!).

Таблица: что где работает

Фича/возможность Server Component Client Component
Доступ к базе данных
Обработка событий
React useState/useEffect
Секреты, API-ключи
Доступ к window/document
Импорт других компонентов ✅ (любых) ✅ (только клиентских и обычных)

6. Пример: серверный и клиентский рендеринг вместе

Давайте соберём простой пример — страницу с приветствием и кнопкой-счётчиком.

1. Серверный компонент:


// app/page.tsx
import Counter from "./components/Counter";

export default function HomePage() {
  return (
    <main>
      <h1>Добро пожаловать!</h1>
      <Counter />
    </main>
  );
}

2. Клиентский компонент:


// app/components/Counter.tsx
"use client";
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Кликнули {count} раз
    </button>
  );
}

Пояснение:

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

7. Типичные ошибки при работе с App Router и рендерингом

Ошибка №1: попытка использовать хуки состояния или window/document в серверном компоненте.
Если вы напишете useState или обратитесь к window в компоненте без "use client", получите ошибку: сервер не знает, что такое браузерные объекты и хуки.

Ошибка №2: забыли добавить "use client" в начало файла клиента.
Без этой директивы компонент останется серверным, даже если вы используете хуки. Это вызовет ошибку компиляции.

Ошибка №3: импорт клиентского компонента в серверный, а потом использовать серверные фичи.
Если вы импортируете клиентский компонент в серверный — всё нормально. Но если наоборот — нельзя! Клиентский компонент не может импортировать серверный, иначе Next.js ругнётся.

Ошибка №4: неправильная организация файлов.
Если вы положите клиентский компонент не в папку components, а прямо в page.tsx и забудете "use client", он останется серверным.

Ошибка №5: попытка использовать секреты или серверные API в клиентском компоненте.
Если вы случайно попытаетесь получить API-ключ или доступ к базе в клиентском компоненте — Next.js не даст этого сделать (и слава богу!).

3
Опрос
Обзор Next.js 15, 7 уровень, 4 лекция
Недоступен
Обзор Next.js 15
Обзор Next.js 15
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ