Зачем оптимизировать производительность
▸Проблема большого bundle
Большой JavaScript bundle замедляет загрузку страницы. Пользователи с медленным интернетом ждут дольше, а Core Web Vitals ухудшаются.
▸Метрики производительности
Lazy Loading компонентов
▸React.lazy
1import { lazy, Suspense } from 'react';23const HeavyComponent = lazy(() => import('./HeavyComponent'));45function App() {6 return (7 <Suspense fallback={<div>Загрузка...</div>}>8 <HeavyComponent />9 </Suspense>10 );11}
▸Условный lazy loading
1function Dashboard() {2 const [showChart, setShowChart] = useState(false);34 return (5 <div>6 <button onClick={() => setShowChart(true)}>Показать график</button>7 {showChart && (8 <Suspense fallback={<Spinner />}>9 <Chart />10 </Suspense>11 )}12 </div>13 );14}
Code Splitting
▸Route-based splitting
1const Home = lazy(() => import('./pages/Home'));2const About = lazy(() => import('./pages/About'));3const Dashboard = lazy(() => import('./pages/Dashboard'));45function App() {6 return (7 <Suspense fallback={<Loading />}>8 <Routes>9 <Route path="/" element={<Home />} />10 <Route path="/about" element={<About />} />11 <Route path="/dashboard" element={<Dashboard />} />12 </Routes>13 </Suspense>14 );15}
▸Preloading
1const Dashboard = lazy(() => import('./pages/Dashboard'));23function App() {4 useEffect(() => {5 // Предзагрузка приidle6 if ('requestIdleCallback' in window) {7 requestIdleCallback(() => {8 import('./pages/Dashboard');9 });10 }11 }, []);1213 return <Routes>...</Routes>;14}
Виртуализация списков
▸Проблема длинных списков
Рендер тысячи элементов замедляет страницу. Виртуализация рендерит только видимые элементы.
▸React-window
1npm install react-window
1import { FixedSizeList } from 'react-window';23function VirtualList({ items }) {4 const Row = ({ index, style }) => (5 <div style={style}>6 {items[index].name}7 </div>8 );910 return (11 <FixedSizeList12 height={500}13 width="100%"14 itemCount={items.length}15 itemSize={35}16 >17 {Row}18 </FixedSizeList>19 );20}
▸react-virtuoso
1npm install react-virtuoso
1import { Virtuoso } from 'react-virtuoso';23function VirtualList({ items }) {4 return (5 <Virtuoso6 style={{ height: '500px' }}7 totalCount={items.length}8 itemContent={(index) => (9 <div>{items[index].name}</div>10 )}11 />12 );13}
Анализ bundle
▸Webpack Bundle Analyzer
1npm install --save-dev webpack-bundle-analyzer
1// next.config.js2const withBundleAnalyzer = require('@next/bundle-analyzer')({3 enabled: process.env.ANALYZE === 'true',4});56module.exports = withBundleAnalyzer({});
▸Визуализация
Запустите ANALYZE=true npm run build для визуализации bundle. Ищите дублирующиеся библиотеки и крупные зависимости.
Оптимизация изображений
▸Next.js Image
1import Image from 'next/image';23<Image4 src="/photo.jpg"5 width={500}6 height={300}7 alt="Описание"8 loading="lazy"9/>
▸WebP формат
Используйте WebP вместо JPEG/PNG. WebP на 25-34% меньше при аналогичном качестве.
Мемоизация
▸React.memo для компонентов
1const ExpensiveList = React.memo(({ items }) => {2 return items.map(item => <ListItem key={item.id} data={item} />);3});
▸useMemo для вычислений
1const sortedItems = useMemo(() => {2 return [...items].sort((a, b) => a.name.localeCompare(b.name));3}, [items]);
Service Workers
▸Кэширование статических ресурсов
1// service-worker.js2self.addEventListener('install', (event) => {3 event.waitUntil(4 caches.open('v1').then((cache) => {5 return cache.addAll([6 '/',7 '/index.html',8 '/styles.css',9 '/app.js',10 ]);11 })12 );13});
Профилирование
▸React DevTools Profiler
Записывайте профиль рендера и анализируйте:
▸Chrome DevTools Performance
Записывайте JavaScript execution, layout и paint для выявления узких мест.
Заключение
Производительность React — это система: lazy loading для маршрутов, виртуализация для списков, мемоизация для вычислений, анализ bundle для оптимизации размера. Используйте profiling инструменты для выявления реальных проблем и оптимизируйте точечно.