---
title: "Оптимізація продуктивності"
description: "Продуктивність на етапах деплою та виконання для Ring Platform — кешування React 19, ревалідація списків, Web Vitals та типові помилки в продакшені"
locale: "uk"
---
# Оптимізація продуктивності

> **Info**
> Фільтруйте за **Засновник** / **Розробник** у боковому меню документації. Ця сторінка замінює старий вигаданий контент (наприклад, `$2.8M revenue`, вигадані приклади dashboard, фейкові SLA Lighthouse). Вказані нижче патерни підтверджені у `next.config.mjs`, `lib/cached-data.ts`, `components/providers/web-vitals-provider.tsx`, `features/analytics/lib/analytics-db.ts`, а також актуальними висновками з деплою в Docker.

Ring Platform фокусується на **швидкому першому рендері** (React 19 Server Components за замовчуванням), **завжди актуальних списках на маркетплейсі** (теги кешу + синхронізація мутацій) та **вимірюваному UX** (інжест Core Web Vitals). Продуктивність — це питання деплою: тайм-аути білду, SSR-підводні камені та інвалідація кешу важливі не менше, ніж фронт-ендова "поліровка".

## Перевірений стек продуктивності

| Рівень            | Механізм                                         | Де реалізовано                                         |
|-------------------|--------------------------------------------------|--------------------------------------------------------|
| **Фреймворк**     | Next.js 16 App Router, `cacheComponents: true`   | `next.config.mjs`                                      |
| **Кешування списків** | `unstable_cache` + `revalidateTag`           | `lib/cached-data.ts`                                   |
| **Дедуплікація запитів** | `React.cache()` на серверних читаннях   | `lib/services/firebase-service-manager.ts`, actions    |
| **read-after-write** | 30с процесний кеш сутності                    | `DatabaseService` `EntityCache`                        |
| **Важкий клієнтський UI**  | `dynamic(..., { ssr: false })`         | `components/docs/mdx-heavy-components.tsx`             |
| **Код у документації**     | Серверний Shiki (`highlightCodeToHtml`)   | `components/docs/code.tsx`                             |
| **Зображення**    | `next/image` WebP/AVIF                           | `next.config.mjs` → `images.formats`                   |
| **UX-метрики**    | `useReportWebVitals` → POST `/api/analytics/web-vitals` | `components/providers/web-vitals-provider.tsx`, `features/analytics/lib/analytics-db.ts` |
| **Ресурсні підказки** | `prefetchDNS` / `preinit` скрипти           | `contexts/app-context.tsx`                             |

### For founders

## Чому продуктивність важлива для вашого клону

Повільні сторінки **опортюніті** та **стору** безпосередньо б'ють по конверсіях: користувачі залишають кошик, продавці бачать порожні дашборди, AI-меджер надсилає сповіщення “зі запізненням”, навіть коли дані актуальні.

### Що власники можуть оптимізувати без коду

  
- **[Оцінити спочатку](/docs/deployment/monitoring.md)** — В адмінці → **Аналітика** показує медіани Web Vitals і клієнтські помилки — зафіксуйте базову лінію до ребрендингу або додавання важких hero‑зображень.

  
- **[Дисципліна роботи з зображеннями](/docs/features/store.md)** — Зображення товарів та сутностей — тільки Blob/CDN URL через `next/image`. Перегруз PNG-графіки hero найчастіше псують LCP у нових клонах.

  
- **[Актуальність списків](/docs/architecture/discovery-mutation-sync.md)** — Після публікації оголошень кеші повинні інвалідовуватись — якщо списки застарілі, налагодьте синхронізацію перед масштабуванням серверів.

  
- **[Локалізаційний обсяг](/docs/features/locale-system.md)** — Менше активних мов (`NEXT_PUBLIC_SUPPORTED_LOCALES`) зменшує обсяг білду та кількість static param при деплої.

### Базові порогові значення Web Vitals (Google, згідно коду)

| Метрика | Добре (≤) | Погано (>)      |
|---------|-----------|-----------------|
| **LCP** | 2.5s      | 4s              |
| **INP** | 200ms     | 500ms           |
| **CLS** | 0.1       | 0.25            |
| **TTFB**| 800ms     | 1.8s            |
| **FCP** | 1.8s      | 3s              |
| **FID** | 100ms     | 300ms           |

Пороги використовуються у `ratingForMetric` із `features/analytics/lib/analytics-db.ts`. Клієнт надсилає рейтинг кожної метрики з `next/web-vitals` (буферизує і POSTить всі разом на `/api/analytics/web-vitals`).

> **Tip**
> Ставте **продуктивність як критерій релізу** для нових запусків: пройдіться Lighthouse по `/`, `/opportunities` і `/store` одразу після деплою — тиждень потому звірте з аналітикою в Адмінці.

### For developers

## Кешування та актуальність списків

```mermaid
sequenceDiagram
    participant Page as RSC list page
    participant UC as unstable_cache
    participant DB as DatabaseService
    participant Mut as create/update service
    participant Sync as sync*Discovery

    Page->>UC: getCachedOpportunitiesForRole
    UC->>DB: query (on miss)
    Mut->>DB: write
    Mut->>Sync: revalidateTag + revalidatePath
    Sync->>UC: tags busted — next request refetches
```

### Кеш списків, розділений по ролям

{`export const getCachedOpportunitiesForRole = (roleKey: UserRolesArray) =>
  unstable_cache(
    async (limit = 20, startAfter?: string) =>
      getOpportunitiesForRole({ userRole: roleKey, limit, startAfter }),
    ['opportunities-list', roleKey],
    { tags: ['opportunities-list', \`opportunities-role-\${roleKey}\`] },
  )

export function invalidateOpportunitiesCache(roleKeys: string[] = []) {
  revalidateTag('opportunities-list', 'max')
  for (const role of roleKeys) revalidateTag(\`opportunities-role-\${role}\`, 'max')
}`}

Цей самий патерн використовується для сутностей (`getCachedEntitiesForRole` / `invalidateEntitiesCache`) та агрегату адмін-статистики новин (`invalidateNewsStatsCache`).

Сервіси мутацій використовують `syncOpportunityDiscovery` / `syncEntityDiscovery` — див. [Discovery mutation sync](/docs/architecture/discovery-mutation-sync.md). **Ніколи** не кешуйте шлях запису; **завжди** інвалідовуйте кеш після CRUD.

### Серверний dedup читання (React.cache)

Обгорніть дорогі серверні фетчі у `cache()` з `react`, щоб паралельні Server Components ділили один виклик до БД на запит (`getCachedDocument` в `lib/services/firebase-service-manager.ts`).

### read-after-write: 30 секунд

`DatabaseService` підтримує нетривалий кеш (`EntityCache` з TTL 30с): створені дані будуть одразу читатись у межах одного процесу — не замінник `revalidateTag`.

## Продакшн-патерни React 19

| Pattern                         | Де у проєкті                 |
|----------------------------------|------------------------------|
| `useActionState`                 | `features/reviews/components/review-form.tsx`         |
| `useOptimistic`                  | `hooks/use-realtime.ts`, `hooks/use-realtime-opportunities.ts` |
| Server Actions + `revalidatePath`| `app/_actions/*.ts`          |

Використовуйте Server Components для контейнерів списків і сутностей; `'use client'` залишайте тільки для форм, тунеля, гаманця, та візуалізацій.

## Підводні камені білду та деплою

### Не SSR-іть важкі візуалізації на сервері

Документаційні і маркетингові графіки підтягуються через `dynamic(..., { ssr: false })` у `mdx-heavy-components.tsx`. Верхньорівневі Mermaid або Shiki сервером викликали **30 секунд завантаження та 503** у production — див. [Docker deployment](/docs/deployment/docker.md).

### `` у документації — асинхронний серверний Shiki

`components/docs/code.tsx` використовує `highlightCodeToHtml` на кожному блоці — не додавайте на ту ж сторінку клієнтські хайлайтери.

### Таймаут білду

`staticPageGenerationTimeout: 180` у `next.config.mjs` — великі дерева документації чи багато мов вимагають акуратної інкрементальної генерації: зменшіть охоплення у `scanDocsStaticParams`, якщо білди не встигають в CI.

### Standalone-білд та тюнінг трейсингу

`next.config.mjs` задає `output: 'standalone'` із `outputFileTracingRoot`, `serverExternalPackages` (Firebase, Auth.js, Solana, nodemailer) і `outputFileTracingIncludes` (i18n, локалі, доки, ring-config, server.ts): контейнерні іміджі містять лише потрібні серверні бандли.

### Оптимізація зображень

У `next.config.mjs`: WebP/AVIF (`images.formats`) та remote patterns для Google avatars, Google Fonts, Vercel Blob і `cdn.ring-platform.org`; специфічні клієнтські патерни — через `collectCloneImageRemotePatterns`. Додавайте нові CDN хости до `images.remotePatterns` при підключенні нового клону.

### Вимірювання регресій

- **Збір:** `WebVitalsProvider` (`components/providers/web-vitals-provider.tsx`), вставлений у `app-client-shell.tsx`  
- **Збереження:** міграція `017_ring_analytics_schema.sql`  
- **Запит:** аналітика в адмінці або `GET /api/analytics/web-vitals?scope=platform` (admin)  
- **Вимкнути записи:** `ANALYTICS_DISABLE_STORAGE=true` для навантажувальних тестів  

Повний огляд інструментів: [Моніторинг і аналітика](/docs/deployment/monitoring.md).

### Ґрунтовний гайд для розробників

Реалізаційні патерни (Firebase cache(), статична генерація, edge-прийоми) — у [Розробка: продуктивність](/docs/development/performance.md) та [Фічі: продуктивність](/docs/features/performance.md). Перед копіюванням зразків із cache()/Firebase завжди звіряйте приклади з тими, що перевірені на postgres‑primary-клонах.

## Дотична документація

  
- [deployment/monitoring](/docs/deployment/monitoring.md) — Наступний крок: health checks, Web Vitals API і аналітика для адмінів.

  
- [deployment/docker](/docs/deployment/docker.md) — За тим же флоу: інциденти мермейд SSR та health-проби.

  
- [architecture/discovery-mutation-sync](/docs/architecture/discovery-mutation-sync.md) — Детальніше: інвалідація кешу після CRUD по сутностях або опортюніті.

  
- [development/performance](/docs/development/performance.md) — До матеріалів: патерни cache(), SSG і edge-примітки для розробників.
