---
title: Default to Server Components, Use Client Only When Needed
impact: CRITICAL
impactDescription: Reduces JavaScript bundle size by 40-60% and improves initial load
tags: architecture, nextjs, rsc, server-components, ssr
---
## Паспорт документа

- Статус документа: living standard
- Актуально на: 28 марта 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении инженерной практики, CI/CD, архитектурных правил или локального workflow
- Область применения: внутренние rule/reference-card документы для инженерной команды
- Связанные документы:
  - [Индекс Agents](../README.md)
  - [Команды разработки](../commands.md)
  - [Инженерные принципы](../../governance/engineering-principles.md)

## Default to Server Components, Use Client Only When Needed

**Impact: CRITICAL (Reduces JS bundle size by 40-60%)**

Every Next.js component is a Server Component by default. Only add `"use client"` when the component genuinely requires browser APIs or interactivity.

**Requires `"use client"`:**
- Event handlers (`onClick`, `onChange`, `onSubmit`)
- React hooks (`useState`, `useEffect`, `useRef`)
- Browser APIs (`window`, `document`, `localStorage`)
- Third-party client libraries (map widgets, animation libraries)

**Does NOT require `"use client"`:**
- Data fetching and display
- Static content rendering
- Layout and navigation structure
- Conditional rendering based on props/data

**Incorrect (unnecessary client component):**

```typescript
"use client"; // Why? This doesn't need any client features!

import { api } from '@/lib/api';

export default function ItemDetailPage({ params }) {
  const [item, setItem] = useState(null);

  useEffect(() => {
    api.catalog.getItemBySlug(params.slug).then(setItem);
  }, []);

  if (!item) return <Skeleton />;
  return <div>{item.name}</div>;
}
```

**Correct (Server Component with client islands):**

```typescript
// app/item/[slug]/page.tsx — Server Component (no directive)
import { api } from '@/lib/api';
import { notFound } from 'next/navigation';
import { ItemActions } from './ItemActions'; // Client island

export default async function ItemDetailPage({ params }: { params: { slug: string } }) {
  const item = await api.catalog.getItemBySlug(params.slug);
  if (!item) notFound();

  return (
    <div>
      <h1>{item.name}</h1>
      <p>{item.description}</p>
      {/* Only this part is a Client Component */}
      <ItemActions itemId={item.id} />
    </div>
  );
}

// app/item/[slug]/ItemActions.tsx — Client Component (needs interactivity)
"use client";

import { useTranslations } from 'next-intl';

export function ItemActions({ itemId }: { itemId: string }) {
  const t = useTranslations('item');
  const [showModal, setShowModal] = useState(false);
  return <button onClick={() => setShowModal(true)}>{t('submitLead')}</button>;
}
```

**Pattern: Client Islands**
Keep the page as a Server Component. Extract only the interactive parts into small Client Components ("islands") and pass serializable data as props.
