---
title: "Продуктивність"
description: "Патерни продуктивності, специфічні для Ring Platform — React 19 cache(), імітація Firebase під час збірки, оптимізація запитів DatabaseService, серверні компоненти та Firebase Admin SDK."
locale: "uk"
---
# Оптимізація продуктивності

Стратегії профілювання та оптимізації, специфічні для Ring Platform. Цей документ охоплює реальні патерни кодової бази. Щодо очікувань продуктивності для користувачів див. [Продуктивність](/docs/en/features/performance.md). Щодо посилення продуктивності в продакшені див. [Продуктивність розгортання](/docs/en/deployment/performance.md). Щодо загальних конвенцій розробки див. [Найкращі практики](/docs/en/development/best-practices.md).

> **Warning**
> Ring Platform **не** використовує Firestore на стороні клієнта. Firebase використовується виключно через Admin SDK у `lib/firebase-admin.server.ts`. Єдиний клієнтський код Firebase — це `public/firebase-messaging-sw.js` для push-сповіщень FCM.

### For founders

## Що впливає на час завантаження

Ring Platform завантажується швидко, оскільки більшість сторінок — це **серверні компоненти React**, що рендеряться на сервері. Ключові фактори, що впливають на продуктивність:

- **Кешування серверних даних** — повторні читання Firestore під час одного запиту дедуплікуються за допомогою `cache()` з React 19.
- **Оптимізації під час збірки** — Firebase Admin імітується під час статичної генерації, скорочуючи час збірки приблизно на 31%.
- **Мінімальний клієнтський JavaScript** — лише сторінки з інтерактивністю (форми, мапи, оформлення замовлення) використовують клієнтські компоненти.
- **Ресурси через CDN** — статичні сторінки попередньо збираються та обслуговуються з кешу на краю мережі.

## Доступні оптимізації продуктивності

| Оптимізація | Перевага |
|---|---|
| React 19 cache() | Дедуплікація читань Firestore на один запит |
| Імітація Firebase під час збірки | ~31% швидші збірки, запобігає 22+ зайвим ініціалізаціям |
| Рівень запитів DatabaseService | Уніфікований PostgreSQL + Firestore з кешуванням |
| Серверні компоненти за замовчуванням | Без клієнтського JS для більшості сторінок |
| WayForPay лише на сервері | Жодна логіка платежів не потрапляє на клієнт |
| FCM Service Worker | Push-сповіщення обробляються поза головним потоком |

### For developers

## React 19 cache() для дедуплікації даних

Модуль `firebase-service-manager.ts` обгортає кожне читання Firestore Admin SDK за допомогою `cache()` з React 19. Це запобігає дублюванню запитів у межах одного проходу рендерингу серверного компонента.

```typescript
import { getCachedDocument, getCachedCollection } from '@/lib/services/firebase-service-manager'

// Кілька викликів одного документа під час SSG зводяться до одного читання Firestore
const entity = await getCachedDocument('entities', 'abc123')
const sameEntity = await getCachedDocument('entities', 'abc123') // cache hit

// Запити колекцій також кешуються на один запит
const activeEntities = await getCachedCollection('entities', {
  where: { field: 'status', operator: '==', value: 'active' },
  orderBy: { field: 'createdAt', direction: 'desc' },
  limit: 20
})
```

Функція `cache()` імпортується з React 19 — це не власна реалізація. Усі функції кешованого читання знаходяться у `lib/services/firebase-service-manager.ts` і працюють з `firebase-admin/firestore`.

> **Tip**
> Область кешу — лише поточний прохід рендерингу серверного компонента. Після надсилання відповіді кеш видаляється. Для довготривалого кешування використовуйте `revalidate` на fetch або виділений шар кешування.

## Імітація Firebase під час збірки

Під час `next build` встановлюється `NEXT_PHASE=phase-production-build`. Модуль у `lib/firebase/build-mock.server.ts` виявляє це та повертає імітовані екземпляри Firestore, Auth і RTDB. Це запобігає приблизно 22 ініціалізаціям Firebase Admin, які інакше виконувалися б під час статичної генерації.

```typescript
import { isBuildTime, getMockFirebaseServices } from '@/lib/firebase/build-mock.server'

if (isBuildTime()) {
  const { mockDb, mockAuth } = getMockFirebaseServices()
  // mockDb.collection('test').get() повертає порожні результати
  // Облікові дані Firebase не потрібні під час збірки
}
```

Шар імітації реалізує повний інтерфейс запитів Firestore з ланцюжковими методами `where()`, `orderBy()`, `limit()` та пагінацією — усі повертають порожні набори результатів. Методи Auth повертають безпечні об'єкти користувачів за замовчуванням. Це активне в `lib/firebase/build-mock.server.ts:36`.

## Оптимізація запитів DatabaseService

Рівень абстракції бази даних у `lib/database/DatabaseService.ts` надає уніфікований API запитів для PostgreSQL і Firestore із вбудованим кешуванням сутностей на 30 секунд.

```typescript
import { getDatabaseService } from '@/lib/database/DatabaseService'

const db = getDatabaseService()
const result = await db.query({
  collection: 'entities',
  filters: { status: 'active' },
  orderBy: { field: 'createdAt', direction: 'desc' },
  pagination: { limit: 20 }
})

if (!result.success) {
  throw result.error || new Error('Query failed')
}
```

Сервіс включає клас `EntityCache` з інвалідацією на основі TTL. Для узгодженості читання після запису операції запису інвалідують відповідні ключі.

> **Warning**
> Не викликайте `db.users.findById()` або подібні патерни. API DatabaseService використовує `db.query({ collection, filters })` з одним об'єктом параметрів. Див. `lib/database/DatabaseService.ts:74` для повного інтерфейсу.

## Серверні компоненти за замовчуванням

Усі сторінки в `app/` є серверними компонентами, якщо вони не містять директиви `'use client'`. Це усуває клієнтський JavaScript для більшості маршрутів. Клієнтські компоненти використовуються лише для:

- Інтерактивних форм (оформлення замовлення, онбординг продавців)
- Відображення мап (Ringdom Maps)
- Інтерфейсів гаманців та платежів
- Панелей адміністрування

Шукайте `'use client'` у `app/`, щоб побачити повний перелік клієнтських компонентів.

## Обробка фонових повідомлень FCM

Firebase Cloud Messaging повністю обробляється в Service Worker у `public/firebase-messaging-sw.js`. Push-події обробляються без пробудження головного потоку JavaScript. Клієнт лише реєструє Service Worker і передає FCM-токен на сервер.

## WayForPay лише на сервері

Платіжні запити виконуються виключно на стороні сервера. Жодні облікові дані продавця WayForPay, HMAC-ключі або логіка платежів не потрапляють у браузер. Клієнт надсилає посилання на замовлення; сервер формує та верифікує всі платіжні дані. Див. [Інтеграція WayForPay](/docs/en/features/wayforpay-integration.md).

## Стратегії рендерингу Next.js 16

Використовуйте експорт `force-dynamic`, `force-static` або `revalidate` для кожної сторінки, щоб контролювати рендеринг:

```typescript
// Статична сторінка, ревалідується кожні 60 секунд
export const revalidate = 60

// Повністю динамічна — без кешування
export const dynamic = 'force-dynamic'
```

Статична генерація є режимом за замовчуванням. Явно позначайте сторінки як `force-dynamic`, якщо вони відображають дані конкретного користувача.

## Показники продуктивності

- First Contentful Paint: < 1.5 с
- Largest Contentful Paint: < 2.5 с
- First Input Delay: < 100 мс
- Cumulative Layout Shift: < 0.1
- Скорочення часу збірки завдяки імітації Firebase: ~31%

## Моніторинг

Web Vitals збираються в продакшені. Налаштуйте відстеження аналітики в середовищі розгортання. Для аналізу під час збірки виконайте:

```bash
npm run build
npm run analyze
```

Модуль `firebase-service-manager.ts` також надає внутрішні метрики кешу:

```typescript
import { getCacheMetrics } from '@/lib/services/firebase-service-manager'

const metrics = getCacheMetrics()
console.log(`Hit rate: ${metrics.hitRate.toFixed(1)}%`)
```

---

> **Info**
> Щодо очікувань продуктивності для користувачів див. [Продуктивність (користувач)](/docs/en/features/performance.md). Щодо моніторингу продакшену та налаштування інфраструктури див. [Продуктивність розгортання](/docs/en/deployment/performance.md). Щодо загальних конвенцій розробки див. [Найкращі практики](/docs/en/development/best-practices.md).
