Разработка гибридного рендеринга (SSR + CSR) для веб-приложения

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

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка гибридного рендеринга (SSR + CSR) для веб-приложения
Сложная
~5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Разработка гибридного рендеринга (SSR + CSR) для веб-приложения

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

Это не компромисс «взяли чуть-чуть от каждого» — это точная архитектурная настройка под требования каждой части продукта.

Модели гибридного рендеринга

По маршрутам (route-level rendering): каждый маршрут объявляет свою стратегию. Next.js, Nuxt 3 и SvelteKit поддерживают это нативно.

По компонентам (component-level rendering): Server Components рендерятся на сервере, Client Components — на клиенте. Граница проходит внутри одного маршрута.

По сегментам (segment-level rendering): шапка и навигация — статика, основной контент — SSR, виджеты (чат, уведомления) — CSR.

Конфигурация в Next.js App Router

// next.config.ts — routeRules / export config
export const revalidate = 3600; // По умолчанию: ISR с TTL 1 час

Каждый сегмент маршрута управляет рендерингом независимо:

app/
  (marketing)/          # Группа без layout-влияния
    page.tsx            # SSG — статическая главная
    about/page.tsx      # SSG
    blog/
      page.tsx          # ISR — список постов
      [slug]/page.tsx   # ISR — пост
  (app)/
    layout.tsx          # Серверный layout с проверкой сессии
    dashboard/
      page.tsx          # SSR — дашборд с реальными данными
    reports/
      page.tsx          # CSR — тяжёлые графики, только клиент
// app/(app)/reports/page.tsx — принудительный CSR
'use client'; // Весь маршрут как клиентский компонент

import dynamic from 'next/dynamic';

// Тяжёлые библиотеки только на клиенте
const RechartsChart = dynamic(() => import('@/components/charts/RechartsChart'), {
  ssr: false,
  loading: () => <ChartSkeleton />,
});

Конфигурация в Nuxt 3

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Публичный сайт
    '/': { prerender: true },
    '/about': { prerender: true },
    '/blog/**': { isr: 3600 },

    // API и приложение
    '/api/**': { cors: true },
    '/app/**': { ssr: false },      // SPA для закрытых разделов
    '/admin/**': { ssr: true },     // SSR для admin-панели (SEO не нужен, но нужна быстрая первая загрузка)
  },
});

Server и Client Components — граница рендеринга

React Server Components (Next.js App Router) — ключ к гибридности на уровне компонентов:

// Серверный компонент — запрос прямо к БД, без API-round-trip
// app/products/page.tsx
import { db } from '@/lib/db';
import { ProductCard } from './product-card'; // Серверный
import { FilterBar } from './filter-bar';     // Клиентский

export default async function ProductsPage({
  searchParams
}: {
  searchParams: { category?: string; sort?: string }
}) {
  // Этот код выполняется только на сервере
  const products = await db.product.findMany({
    where: { category: searchParams.category },
    orderBy: { [searchParams.sort ?? 'name']: 'asc' },
    include: { images: { take: 1 } },
  });

  return (
    <div>
      {/* Клиентский компонент — управляет фильтрами через URL */}
      <FilterBar initialCategory={searchParams.category} />

      {/* Серверный компонент — просто рендерит данные */}
      <div className="grid grid-cols-3 gap-4">
        {products.map(product => (
          <ProductCard key={product.id} product={product} />
        ))}
      </div>
    </div>
  );
}
// filter-bar.tsx — клиентский компонент
'use client';
import { useRouter, useSearchParams } from 'next/navigation';

export function FilterBar({ initialCategory }: { initialCategory?: string }) {
  const router = useRouter();
  const params = useSearchParams();

  function setCategory(category: string) {
    const newParams = new URLSearchParams(params);
    newParams.set('category', category);
    router.push(`?${newParams.toString()}`);
  }

  return (
    <nav>
      {CATEGORIES.map(cat => (
        <button key={cat.id} onClick={() => setCategory(cat.id)}>
          {cat.name}
        </button>
      ))}
    </nav>
  );
}

Передача данных между Server и Client компонентами

Server Components не могут принимать функции от Client Components — только сериализуемые данные:

// Правильно: серверные данные как props клиентского компонента
export default async function Page() {
  const user = await getUser(); // Серверный fetch
  return <UserProfile user={user} />; // user — сериализуемый объект
}

// Неправильно: нельзя передать функцию из Server в Client
// return <Button onClick={serverFunction} /> // Ошибка компиляции

Для серверных действий (мутаций) используются Server Actions:

// actions.ts
'use server';
import { revalidatePath } from 'next/cache';

export async function updateProduct(id: string, data: Partial<Product>) {
  await db.product.update({ where: { id }, data });
  revalidatePath(`/products/${id}`); // Инвалидировать кэш
}

// Клиентский компонент вызывает серверный экшен напрямую
'use client';
import { updateProduct } from './actions';

function EditForm({ product }: { product: Product }) {
  return (
    <form action={async (formData) => {
      'use server'; // Встроенный серверный экшен
      await updateProduct(product.id, {
        name: formData.get('name') as string,
      });
    }}>
      <input name="name" defaultValue={product.name} />
      <button type="submit">Сохранить</button>
    </form>
  );
}

Стриминг и Suspense в гибридной архитектуре

// Параллельная загрузка независимых серверных данных
import { Suspense } from 'react';

export default function DashboardPage() {
  return (
    <div>
      {/* Рендерится немедленно — не ждёт данных */}
      <DashboardHeader />

      {/* Каждый блок стримится независимо */}
      <Suspense fallback={<StatsSkeleton />}>
        <Stats />  {/* async компонент с fetch */}
      </Suspense>

      <Suspense fallback={<ChartSkeleton />}>
        <RevenueChart />
      </Suspense>

      <Suspense fallback={<TableSkeleton />}>
        <RecentOrders />
      </Suspense>
    </div>
  );
}

Пользователь видит шапку мгновенно, блоки появляются по мере готовности данных — без блокировки всей страницы.

Метрики и компромиссы

Стратегия TTFB TTI SEO Сложность
Чистый SSR Высокий Средний Отлично Средняя
Чистый CSR Низкий Высокий Плохо Низкая
Чистый SSG Минимальный Минимальный Отлично Низкая
Гибрид (App Router) Низкий Низкий Отлично Высокая

Гибридный рендеринг максимально эффективен, но требует понимания модели — где проходит граница server/client, как работает кэш, как избежать waterfall запросов.

Сроки реализации

  • Неделя 1–2: проектирование границ server/client по маршрутам, настройка Next.js App Router или Nuxt 3
  • Неделя 3: Server Components для публичных страниц, Server Actions для мутаций
  • Неделя 4: Client Components для интерактивных частей, Suspense-границы
  • Неделя 5: ISR и кэширование для публичного контента, оптимизация TTFB
  • Неделя 6: тестирование, мониторинг Core Web Vitals, деплой