← Назад к вопросам

Где рендерятся серверные компоненты?

3.0 Senior🔥 111 комментариев
#React#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Где рендерятся серверные компоненты?

Отличный вопрос о современной архитектуре фронтенда. Это ключевая особенность Next.js 13+ и паттерна Server Components.

Краткий ответ

Серверные компоненты рендерятся на сервере (Node.js процесс), результат отправляется клиенту как HTML и специальный React Server Component Payload.

Где это происходит

1. На сервере (Server-Side)

// app/page.jsx - это Server Component по умолчанию в Next.js 13+
import { db } from "@/lib/db";
import { ProductCard } from "@/components/ProductCard";

// Это выполнится на сервере
export default async function ProductsPage() {
  // ✅ Прямой доступ к БД
  const products = await db.query("SELECT * FROM products");
  
  // ✅ Может использовать secrets
  const apiKey = process.env.SECRET_API_KEY;
  const data = await fetch("https://internal-api.com", {
    headers: { Authorization: `Bearer ${apiKey}` }
  });
  
  return (
    <div>
      {products.map((product) => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

Этот код НИКОГДА не попадет в бандл браузера. Он выполняется только на сервере.

Процесс рендеринга

Шаг 1: Сборка (Build time)

// next.config.js
module.exports = {
  experimental: {
    serverActions: true // Включаем Server Actions
  }
};

Ди сборке Next.js:

  • Анализирует какие компоненты — Server Components
  • Какие — Client Components
  • Генерирует оптимизированный bundle

Шаг 2: Runtime (Во время запроса)

1. Браузер отправляет запрос → GET /products
2. Next.js сервер получает запрос
3. Выполняет Server Component код
4. Запрашивает данные из БД
5. Рендерит React дерево на сервере
6. Отправляет результат браузеру
7. Браузер выводит HTML + гидрирует Client Components

Server Component vs Client Component

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

// app/components/UserProfile.jsx
// Без "use client" — это Server Component

import { getUserData } from "@/lib/db";

export default async function UserProfile({ userId }) {
  // Может быть async!
  const user = await getUserData(userId);
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

Client Component

// app/components/InteractiveButton.jsx
"use client"; // Явное указание

import { useState } from "react";

export default function InteractiveButton() {
  const [count, setCount] = useState(0);
  
  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}

Разница:

  • Server Component → выполняется только на сервере
  • Client Component → отправляется в браузер, выполняется там

Архитектура рендеринга

┌─────────────────────────────────────────┐
│         Client (Browser)                │
│  - DOM                                  │
│  - Event Listeners                      │
│  - Interactive UI                       │
└──────────────┬──────────────────────────┘
               ↑ HTTP (HTML + RSC Payload)
               ↓
┌──────────────────────────────────────────┐
│      Server (Node.js Runtime)           │
│  - Database Access                      │
│  - Secret Keys                          │
│  - File System                          │
│  - Server Component Rendering           │
└──────────────────────────────────────────┘

Практический пример

// app/page.jsx - Server Component
import { Suspense } from "react";
import { PostList } from "@/components/PostList";
import { PostSkeleton } from "@/components/PostSkeleton";

async function getPosts() {
  // Выполняется на сервере
  const response = await fetch("https://api.example.com/posts", {
    headers: { "Authorization": `Bearer ${process.env.API_SECRET}` }
  });
  return response.json();
}

export default function Page() {
  return (
    <main>
      <h1>Blog Posts</h1>
      {/* Streaming: Suspense граница для postupных данных */}
      <Suspense fallback={<PostSkeleton />}>
        <PostList postsPromise={getPosts()} />
      </Suspense>
    </main>
  );
}

React Server Component Payload

Это специальный формат, который отправляется браузеру:

// Что браузер получает после рендеринга Server Component
// Это не просто HTML, а специальный формат

M1:{"id":"./app/page.jsx","chunks":[],"name":"Page","async":false}
M2:{"id":"./components/Header.jsx","chunks":[],"name":"Header","async":false}
J0:["@1","span",null,{"children":"Hello World"}]

Этот payload позволяет браузеру:

  • Гидрировать интерактивные компоненты
  • Обновлять части страницы без полного перезагрузки
  • Работать с React Query и другими state-менеджерами

Streaming и Suspense

Server Components поддерживают streaming — отправка контента частями:

// app/dashboard/page.jsx
import { Suspense } from "react";
import { UserStats } from "@/components/UserStats";
import { RecentActivity } from "@/components/RecentActivity";

async function getUserStats(userId) {
  // Может быть медленно
  await new Promise(resolve => setTimeout(resolve, 1000));
  return { views: 1000, followers: 500 };
}

async function getActivity(userId) {
  // Может быть быстро
  return [{ id: 1, text: "Posted" }, { id: 2, text: "Liked" }];
}

export default function Dashboard({ params }) {
  return (
    <div>
      {/* Эта часть загружается быстро */}
      <Suspense fallback={<div>Loading activity...</div>}>
        <RecentActivity activityPromise={getActivity(params.userId)} />
      </Suspense>
      
      {/* Эта часть может быть медленнее */}
      <Suspense fallback={<div>Loading stats...</div>}>
        <UserStats statsPromise={getUserStats(params.userId)} />
      </Suspense>
    </div>
  );
}

Преимущества Server Components

1. Безопасность

// Secrets не попадают в браузер
const password = process.env.DB_PASSWORD; // ✅ Только на сервере

2. Производительность

// Нет JavaScript в браузере для статичного контента
// Размер бандла меньше

3. Прямой доступ к БД

// Нет лишних API запросов
const data = await db.query("SELECT...");

4. Streaming

// Отправка контента по частям
// Улучшена Core Web Vitals

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

  • Запросы к БД
  • Скрытые API ключи
  • Работа с файловой системой
  • Крупные библиотеки (которые сокращают размер бандла)
  • Аутентификация

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

  • Интерактивность (onClick, onChange, и т.д.)
  • Хуки (useState, useEffect, useContext)
  • Браузерный API (localStorage, sessionStorage)
  • Слушание событий

Заключение

Серверные компоненты рендерятся на сервере (Node.js процесс), результат отправляется клиенту как HTML + React Server Component Payload. Это позволяет:

  • Безопасно работать с секретами
  • Уменьшить размер JavaScript бандла
  • Улучшить производительность
  • Использовать Suspense для streaming

Это один из главных паттернов современного фронтенда с Next.js 13+.

Где рендерятся серверные компоненты? | PrepBro