Патерни продуктивності React, які ми використовуємо на продакшні
Практичні патерни продуктивності React із продуктів fluxLab.dev: code splitting, мемоізація, віртуалізація та оптимізація зображень.
Вступ
Продуктивність у fluxLab.dev — це не запізніла думка, а фіча. У наших продуктах ми виробили патерни, що тримають React-додатки швидкими навіть при зростанні складності. Це техніки, які дали найбільший ефект.
Патерн 1: Server Components за замовчуванням
У Next.js App Router кожен компонент — Server Component, поки ви не додасте 'use client'. Ми використовуємо це максимально агресивно.
Правило
Додавайте 'use client' лише коли вам потрібні:
- Обробники подій (
onClick,onChange) - Browser API (
localStorage,window) - React-хуки (
useState,useEffect)
У фронтенді Jobber 70% компонентів — Server Components. Вони додають нуль JavaScript у клієнтський бандл.
Патерн 2: Lazy load нижче фолду
Все, що не видно при початковому завантаженні сторінки, завантажується лінійно:
import dynamic from 'next/dynamic';
const Analytics = dynamic(() => import('./analytics'), {
loading: () => <AnalyticsSkeleton />,
});
Для аналітичної панелі Jobber lazy loading компонентів графіків зменшив початковий бандл на 120КБ. Користувачі бачать макет сторінки миттєво, а графіки завантажуються під час скролу.
Патерн 3: Оптимізація зображень з Next/Image
Кожне зображення в наших продуктах використовує next/image з правильною конфігурацією:
<Image
src={screenshot.src}
alt={screenshot.alt}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1100px"
/>
Атрибут sizes критично важливий — він повідомляє браузеру, який розмір зображення завантажити залежно від ширини viewport. Без нього браузер щоразу завантажує найбільше зображення.
Патерн 4: Дебаунс інпутів пошуку та фільтрів
Пошук у реальному часі коштує дорого. Ми дебаунсимо всі пошукові інпути на 300мс:
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
У списку компаній Jobber це зменшило кількість API-викликів на 80%, зберігаючи відгукливість інтерфейсу.
Патерн 5: Віртуалізація довгих списків
Для списків з понад 50 елементами ми використовуємо віртуалізацію. У DOM рендеряться лише видимі елементи. Kanban-дошка в Jobber використовує цей патерн — навіть із сотнями карток заявок скрол залишається плавним, бо в DOM одночасно перебуває лише 10-15 карток.
Патерн 6: Оптимістичні оновлення для Drag-and-Drop
Коли користувач перетягує картку заявки між колонками на Kanban-дошці Jobber, ми оновлюємо UI миттєво — ще до завершення виклику API. Якщо виклик API завершується невдало, ми відкатуємо зміну і показуємо помилку.
Це робить drag-and-drop миттєвим на відчуття, навіть попри те, що оновлення на бекенді триває 50-100мс.
Патерн 7: Попереднє завантаження критичних даних
Для сторінок, які користувач, ймовірно, відвідає далі, ми завантажуємо дані заздалегідь при наведенні курсору:
<Link
href={`/projects/${slug}`}
onMouseEnter={() => prefetchProject(slug)}
>
Це знімає 200-400мс із сприйманого часу навігації, бо дані вже закешовані в момент кліку користувача.
Патерн 8: Аналіз бандлу
Ми запускаємо @next/bundle-analyzer на кожному релізі, щоб відловлювати регресії розміру бандлу. Будь-яке зростання понад 10КБ потребує обґрунтування.
Типові знахідки:
- Імпорт цілої бібліотеки іконок замість окремих іконок
- Бібліотеки дат (moment.js → date-fns → нативний Intl)
- Невикористаний CSS з бібліотек компонентів
Вимірювання продуктивності
Ми відстежуємо Core Web Vitals у продакшні:
- LCP (Largest Contentful Paint): ціль менше 2.5с
- INP (Interaction to Next Paint): ціль менше 200мс
- CLS (Cumulative Layout Shift): ціль менше 0.1
Наш портфоліо-сайт (flux-lab.dev) набирає 95+ балів у Lighthouse за всіма метриками.
Висновок
Оптимізація продуктивності React — це послідовний вибір розумних рішень: Server Components замість Client Components, lazy loading замість жадібного завантаження та вимірювання перед оптимізацією. Ці патерни тримають наші продукти швидкими в усіх наших продакшн-розгортаннях.
Якщо ваш React-застосунок здається повільним і ви не знаєте чому, ми можемо допомогти. Кожна співпраця починається з вимірювання.
Читайте також
Як ми будуємо продакшн веб-додатки на Next.js
Як влаштований наш сайт на Next.js 16: Server Components, маршрути з префіксами локалей, hreflang на кожній сторінці, форми з Zod, Tailwind 4 і Docker.
Уроки продуктивності PostgreSQL з досвіду 6 SaaS-продуктів
Уроки оптимізації PostgreSQL з експлуатації продакшн SaaS-баз даних у fluxLab.dev: індексація, тюнінг запитів, N+1 запити та пулінг з'єднань.