← Назад к вопросам
Как будешь решать проблему производительности?
2.0 Middle🔥 231 комментариев
#Оптимизация и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как будешь решать проблему производительности?
Методический подход
Производительность — это не гадание. Есть четкая методика: Measure -> Analyze -> Fix -> Verify.
Шаг 1: Measuring (Измерение)
Chrome DevTools Performance
// Открыть DevTools -> Performance -> Record
// Записать типичный user flow
// Или программно:
performance.mark('myFeature-start');
// ... код ...
performance.mark('myFeature-end');
performance.measure('myFeature', 'myFeature-start', 'myFeature-end');
const measure = performance.getEntriesByName('myFeature')[0];
console.log(`Заняло ${measure.duration}ms`);
Core Web Vitals
// Google Web Vitals library
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
getCLS(console.log); // Cumulative Layout Shift
getFID(console.log); // First Input Delay
getFCP(console.log); // First Contentful Paint
getLCP(console.log); // Largest Contentful Paint
getTTFB(console.log); // Time to First Byte
Lighthouse
# CLI запуск
lighthouse https://example.com --view
# Или в DevTools: Lighthouse tab
Network Tab
// Проверить:
// - Размер бандла
// - Кол-во запросов
// - Время загрузки каждого ресурса
// - Неиспользуемый код (Coverage tab)
Шаг 2: Analyzing (Анализ)
Найти "узкие места" (bottlenecks)
// 1. Медленный JavaScript
console.time('expensiveOperation');
processLargeArray(1000000);
console.timeEnd('expensiveOperation'); // 250ms
// 2. Лишние re-renders
function MyComponent() {
const [count, setCount] = useState(0);
const data = computeExpensiveData(); // переделывается при каждом render!
return <div>{count}</div>;
}
// 3. Неоптимизированные изображения
// <img src="4MB.jpg" /> // слишком тяжелое
// 4. Забытые console.log и debugger
function handleClick() {
console.log('debug'); // в продакшене!
debugger; // или это!
doSomething();
}
React Profiler
// DevTools -> Profiler -> Record -> Interact -> Analyze
// Видишь какие компоненты переделываются и сколько времени занимает
Шаг 3: Fixing (Исправление)
1. Code Splitting
// Не загружай всё сразу
const HeavyComponent = dynamic(
() => import('./HeavyComponent'),
{ loading: () => <Spinner />, ssr: false }
);
// Маршруты
const AdminDashboard = lazy(() => import('./AdminDashboard'));
const UserProfile = lazy(() => import('./UserProfile'));
2. Memoization
// Избегай лишних расчетов
const MemoComponent = memo(function MyComponent({ prop }) {
return <div>{prop}</div};
});
// Стабилизируй зависимости
const memoizedValue = useMemo(() => {
return expensiveCalculation(a, b);
}, [a, b]);
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
3. Оптимизация изображений
// Next.js Image (автоматическое сжатие)
import Image from 'next/image';
<Image
src="/large.jpg"
alt="Description"
width={800}
height={600}
priority={false} // lazy load
quality={75} // сжимаем
/>
// WebP формат
<picture>
<source srcSet="image.webp" type="image/webp" />
<img src="image.jpg" alt="" />
</picture>
// Responsive images
<img
src="small.jpg"
srcSet="medium.jpg 768w, large.jpg 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
alt=""
/>
4. Виртуализация списков
// Не рендери 10000 элементов, рендери видимые
import { FixedSizeList } from 'react-window';
function LargeList() {
const Row = ({ index, style }) => (
<div style={style}>Item {index}</div>
);
return (
<FixedSizeList
height={600}
itemCount={10000}
itemSize={35}
width="100%"
>
{Row}
</FixedSizeList>
);
}
5. Минимизация бандла
// Убери неиспользуемый код
// Chrome DevTools -> Coverage -> проверь какой код не используется
// Tree shaking в webpack/vite
// Экспортируй только нужное
export { usefulFunction }; // экспортируется
// uselessFunction не экспортируется -> будет удален
// Lazy load библиотеки
const lodash = () => import('lodash'); // только когда нужна
6. Кеширование
// React Query
const { data } = useQuery({
queryKey: ['users'],
queryFn: api.getUsers,
staleTime: 5 * 60 * 1000, // 5 минут свежести
cacheTime: 10 * 60 * 1000 // кешировать 10 минут
});
// Service Worker
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then(r => r || fetch(e.request))
);
});
7. Асинхронность
// Не блокируй main thread
setTimeout(() => { // отложи
heavyCalculation();
}, 0);
// Используй requestIdleCallback
requestIdleCallback(() => {
analyzeUserBehavior(); // когда браузер свободен
});
// Web Workers для тяжелых расчетов
const worker = new Worker('worker.js');
worker.postMessage({ data: largeData });
worker.onmessage = (e) => console.log(e.data);
Шаг 4: Verification (Проверка)
// Повторяем Шаг 1
performance.mark('after-fix');
// Сравниваем метрики ДО и ПОСЛЕ
// Ожидаемый результат:
// - LCP: было 5s, стало 2s
// - FCP: было 2s, стало 0.8s
// - Бандл: было 500KB, стало 200KB
Пример: Реальная оптимизация
// ДО: 5 сек загрузки
function ProductList() {
const [products, setProducts] = useState([]);
useEffect(() => {
api.getAllProducts().then(setProducts); // загружаем всё
}, []);
return (
<div>
{products.map(p => (
<ProductCard key={p.id} product={p} /> // рендерим всё
))}
</div>
);
}
// ПОСЛЕ: 1.5 сек загрузки
const HeavyProductCard = memo(ProductCard);
function ProductList() {
const { data: products } = useQuery({
queryKey: ['products'],
queryFn: api.getProducts, // пагинация
keepPreviousData: true
});
return (
<FixedSizeList height={800} itemCount={products.length} itemSize={100}>
{({ index, style }) => (
<div style={style}>
<HeavyProductCard product={products[index]} />
</div>
)}
</FixedSizeList>
);
}
Контрольный список оптимизации
- Измерил Core Web Vitals
- Запустил Lighthouse
- Проверил размер бандла
- Удалил мертвый код
- Оптимизировал изображения
- Добавил code splitting
- Убрал лишние re-renders (useMemo, useCallback)
- Внедрил виртуализацию для больших списков
- Настроил кеширование
- Проверил Network tab (запросы, водопад)
- Повторно измерил метрики
- Зафиксировал результат
Заключение
Оптимизация производительности — это систематический процесс, не случайное гаданье. Всегда:
- Меряй текущее состояние
- Анализируй узкие места
- Исправляй по приоритету
- Проверяй результаты
Маленкие оптимизации складываются в большой результат: быстрое приложение = больше пользователей = выше конверсия.