Коротка відповідь
middleReact‑застосунок оптимізується через memoization, lazy loading компонентів та правильне використання useCallback. Вимірюємо продуктивність за допомогою Chrome DevTools Performance, React Profiler та Lighthouse. Порівнюємо кадри (FPS) і час рендеру, щоб виявити bottleneck‑и.
Повне пояснення
Що це і навіщо – оптимізація React‑застосунків зменшує кількість непотрібних рендерів, підвищує швидкодію та знижує використання пам’яті. Це критично для великих SPA, де користувач очікує миттєвих реакцій.
Ключові принципи/терміни –
- React Profiler: інструмент, що вимірює час рендеру кожного компонента.
- React.memo: обгортка, що запобігає рендеру при незмінних пропсах.
- useCallback / useMemo: мемоізація функцій та значень, що зменшує створення нових об’єктів.
- Lazy loading (React.lazy + Suspense): підвантаження компонентів лише при потребі.
- Chunking: розбиття бандла на частини, що зменшує час першого рендеру.
- FPS (Frames Per Second): метрика, що показує плавність анімацій.
- Lighthouse: інструмент Google для оцінки продуктивності, доступності та SEO.
Як це працює – React Profiler збирає дані про час рендеру, а Lighthouse аналізує загальну швидкість завантаження. Після збору метрик можна виявити компоненти, що споживають багато часу, і застосувати memoization або lazy loading.
Практика та реалізація – приклад використання React.memo:
const ExpensiveComponent = React.memo(({data}) => {
/* рендер, що залежить лише від data */
});
Lazy loading:
const LazyComp = React.lazy(() => import('./HeavyComponent'));
Тестування – для unit‑тестів можна перевірити, що компонент не рендериться при незмінних пропсах:
const { rerender } = render(<ExpensiveComponent data={initial} />);
rerender(<ExpensiveComponent data={initial} />); // React.memo запобігає рендеру
Для performance‑тестів використовуйте Jest + react-test-renderer або Cypress.
Дизайн‑рішення – розділяйте UI на малі, незалежні компоненти; використовуйте Context лише там, де це необхідно. Уникайте глобального стану без потреби.
Производительность і масштабирование – збільшуйте кількість worker‑ів у Web Workers для тяжких обчислень; застосовуйте server‑side rendering (Next.js) для швидкого першого рендеру.
Безпека і приватність – оптимізація не впливає безпосередньо на безпеку, але зменшення кількості запитів до API може знизити ризик DoS.
Особливості в контексті React – Next.js 14/15 пропонує App Router з автоматичним code‑splitting; використовуйте next/dynamic для lazy loading.
Оптимізація, типові помилки та edge cases –
- Неправильне використання useEffect без dependencies → нескінченний цикл рендеру.
- Використання об’єктів у пропсах без мемоізації → кожен рендер створює новий об’єкт.
- Занадто глибока ієрархія компонентів → збільшує час рендеру.
- Відсутність key у списках → React не може оптимізувати повторний рендер.
- Використання
React.Fragmentбез ключа → проблеми з оновленням. - Занадто часті запити до API → збільшує навантаження.
- Відсутність memoization у функціональних пропсах → непотрібні рендери.
- Неправильне розміщення useMemo → мемоізація не працює.
Cheatsheet + follow‑up питання –
- Чому
React.memoне працює з об’єктами? → через порівняння посилань. - Як виміряти FPS у Chrome DevTools? → Performance > Paints.
- Які переваги
React.lazyнад звичайним імпортом? → зменшення бандла. - Як перевірити, що компонент не рендериться при незмінних пропсах? → Jest + react-test-renderer.
- Що таке
useCallbackі коли його застосовувати? → мемоізація функцій, що передаються як пропси.