Как оптимизировать React-приложение?
Рендеринг и производительность
Оптимизация React-приложения идёт по трём фронтам: загрузка (bundle), рендеринг (лишние/дорогие рендеры) и данные (запросы). Начинается всегда с измерений.
Измерить, а не гадать
- React DevTools Profiler — какие компоненты рендерятся, как долго и почему.
- Lighthouse / Web Vitals (LCP, INP, CLS) — метрики загрузки и отзывчивости.
- Bundle analyzer — что раздуло бандл.
Загрузка
- Код-сплиттинг: React.lazy + Suspense по маршрутам и тяжёлым виджетам (редактор, графики).
- Урезание бандла: анализатор, замена тяжёлых зависимостей (moment → date-fns), tree-shaking, динамический импорт редких библиотек.
- Сжатие и кеширование статики, CDN; для контентных страниц — SSR/SSG (Next.js).
- Оптимизация изображений (форматы, lazy loading).
Рендеринг
- Убрать лишние рендеры: React.memo + useCallback/useMemo, спуск состояния вниз, разделение контекстов, узкие селекторы стора.
- Дешевле рендер: useMemo для тяжёлых вычислений, виртуализация длинных списков (react-window).
- Отзывчивость: useTransition/useDeferredValue для несрочных обновлений (фильтрация при вводе).
- Дебаунс дорогих реакций на ввод.
Данные
- Кеширование запросов (TanStack Query/SWR): дедупликация, staleTime, фоновые обновления.
- Пагинация/инфинит-скролл вместо «всего сразу»; префетч следующих данных.
- Меньше каскадов «запрос после запроса» — параллелить, поднимать загрузку на уровень маршрута.
Коротко для собеседования
Схема ответа: сначала профилирование (DevTools Profiler, Lighthouse, bundle analyzer), затем — по узкому месту: бандл (code splitting, lazy, лёгкие зависимости), рендеры (memo/useMemo/useCallback, структура состояния, виртуализация, useTransition), данные (кеш запросов, пагинация). Оптимизация без измерений — антипаттерн.