Лучшие практики оптимизации производительности React/Next.js
Чему вы научитесь
- 🎯 Позволить AI автоматически обнаруживать проблемы производительности в коде React и давать предложения по оптимизации
- ⚡ Устранить каскадную загрузку, ускорить загрузку страниц в 2-10 раз
- 📦 Оптимизировать размер пакета, уменьшить время начальной загрузки
- 🔄 Уменьшить повторный рендеринг, улучшить скорость отклика страниц
- 🏗️ Применять производственные лучшие практики инженерной команды Vercel
Текущие проблемы
Вы написали React код, но чувствуете, что что-то не так:
- Страница загружается медленно, в Developer Tools не видно проблем
- Код, сгенерированный AI, работает, но не ясно, соответствует ли он лучшим практикам производительности
- Видите, как быстро работают приложения Next.js других людей, а ваше — лагает
- Знаете некоторые методы оптимизации (например,
useMemo,useCallback), но не знаете, когда их использовать - Каждый раз при анализе кода вручную проверяете проблемы производительности, низкая эффективность
На самом деле, инженерная команда Vercel уже разработала набор из 57 правил оптимизации производительности, проверенных на практике, охватывающих все сценарии от "устранения каскадной загрузки" до "расширенных шаблонов". Теперь эти правила упакованы в Agent Skills, и вы можете позволить AI автоматически помогать вам проверять и оптимизировать код.
Что такое "Agent Skills"
Agent Skills — это набор расширяемых навыков для AI-агентов кодирования (таких как Claude, Cursor, Copilot). После установки AI будет автоматически применять эти правила в соответствующих задачах, как если бы вы дали AI мозг инженера Vercel.
Когда использовать этот метод
Типичные сценарии использования навыков лучших практик React:
- ❌ Не применимо: простые статические страницы, компоненты без сложного взаимодействия
- ✅ Применимо:
- Написание новых компонентов React или страниц Next.js
- Реализация получения данных на клиенте или сервере
- Анализ или рефакторинг существующего кода
- Оптимизация размера пакета или времени загрузки
- Пользователи сообщают о лагах на странице
🎒 Подготовка перед началом
Предварительная проверка
Перед началом убедитесь, что вы:
- Установили Agent Skills (см. Руководство по установке)
- Знакомы с основами React и Next.js
- Имеете проект React/Next.js для оптимизации
Основная идея
Оптимизация производительности React — это не только использование нескольких Hook, но и решение проблем на уровне архитектуры. 57 правил Vercel разделены по приоритетам на 8 категорий:
| Приоритет | Категория | Фокус | Типичный прирост |
|---|---|---|---|
| CRITICAL | Устранение каскадной загрузки | Избегание последовательных async операций | 2-10× улучшение |
| CRITICAL | Оптимизация сборки | Уменьшение начального размера пакета | Значительное улучшение TTI/LCP |
| HIGH | Производительность сервера | Оптимизация получения данных и кеширования | Уменьшение нагрузки на сервер |
| MEDIUM-HIGH | Получение данных на клиенте | Избегание повторных запросов | Уменьшение сетевого трафика |
| MEDIUM | Оптимизация повторного рендеринга | Уменьшение ненужных повторных рендеров | Улучшение скорости отклика интерфейса |
| MEDIUM | Производительность рендеринга | Оптимизация выполнения CSS и JS | Улучшение кадровой частоты |
| LOW-MEDIUM | Производительность JavaScript | Микрооптимизация выполнения кода | 5-20% улучшение |
| LOW | Расширенные шаблоны | Оптимизация специальных сценариев | Граничные случаи |
Основные принципы:
- Сначала решайте проблемы уровней CRITICAL и HIGH — эти изменения дают наибольшую отдачу
- Начните с потока данных — сначала оптимизируйте асинхронные операции и получение данных
- Затем оптимизируйте рендеринг — в последнюю очередь рассмотрите
useMemo,useCallbackи т.д.
Следуйте за мной
Шаг 1: Запуск AI-анализа производительности
Откройте ваш проект React/Next.js, введите в Claude или Cursor:
Review this React component for performance issuesили
Apply React best practices to optimize this codeВы должны увидеть: AI активирует навык vercel-react-best-practices и начнет применять правила для проверки кода.
Шаг 2: AI автоматически обнаруживает проблемы
AI будет проверять код построчно, обнаруживая проблемы и давая предложения по исправлению. Например:
// ❌ Ваш исходный код (с проблемой)
async function UserProfile({ userId }: { userId: string }) {
const user = await fetchUser(userId)
const posts = await fetchUserPosts(userId)
const comments = await fetchUserComments(userId)
return <div>...</div>
}Обратная связь AI:
⚠️ async-parallel: 3 независимых запроса выполняются последовательно, что вызывает каскадную загрузку
Влияние: CRITICAL (2-10× улучшение)
Предложение:
Используйте Promise.all() для параллельного выполнения независимых запросов, уменьшив 3 сетевых обхода до 1.Оптимизированный код от AI:
// ✅ После оптимизации (параллельное получение)
async function UserProfile({ userId }: { userId: string }) {
const [user, posts, comments] = await Promise.all([
fetchUser(userId),
fetchUserPosts(userId),
fetchUserComments(userId),
])
return <div>...</div>
}Шаг 3: Примеры распространенных проблем
Ниже несколько типичных проблем производительности и их решения:
Проблема 1: Большой компонент приводит к слишком большому начальному Bundle
// ❌ Ошибка: редактор Monaco загружается с главным Bundle (~300KB)
import { MonacoEditor } from './monaco-editor'
function CodePanel({ code }: { code: string }) {
return <MonacoEditor value={code} />
}// ✅ Правильно: динамический импорт, загрузка по требованию
import dynamic from 'next/dynamic'
const MonacoEditor = dynamic(
() => import('./monaco-editor').then(m => m.MonacoEditor),
{ ssr: false }
)
function CodePanel({ code }: { code: string }) {
return <MonacoEditor value={code} />
}Правило: bundle-dynamic-imports (CRITICAL)
Проблема 2: Необходимый Re-render
// ❌ Ошибка: при каждом обновлении родительского компонента ExpensiveList повторно рендерится
function Parent() {
const [count, setCount] = useState(0)
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveList items={largeArray} />
</div>
)
}// ✅ Правильно: оборачиваем React.memo, чтобы избежать ненужных повторных рендеров
const ExpensiveList = React.memo(function ExpensiveList({ items }: { items: Item[] }) {
// ...
})
function Parent() {
const [count, setCount] = useState(0)
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveList items={largeArray} />
</div>
)
}Правило: rerender-memo (MEDIUM)
Проблема 3: Производное состояние в Effect
// ❌ Ошибка: ненужный Effect и дополнительный Re-render
function Component({ items }: { items: Item[] }) {
const [filteredItems, setFilteredItems] = useState<Item[]>([])
useEffect(() => {
setFilteredItems(items.filter(item => item.isActive))
}, [items])
return <div>{filteredItems.map(...)}</div>
}// ✅ Правильно: производное состояние вычисляется при рендеринге, без Effect
function Component({ items }: { items: Item[] }) {
const filteredItems = items.filter(item => item.isActive)
return <div>{filteredItems.map(...)}</div>
}Правило: rerender-derived-state-no-effect (MEDIUM)
Шаг 4: Оптимизация производительности сервера (специфично для Next.js)
Если вы используете Next.js, AI также проверит производительность сервера:
// ❌ Ошибка: несколько независимых fetch выполняются последовательно
async function Dashboard() {
const user = await fetchUser()
const stats = await fetchStats()
const notifications = await fetchNotifications()
return <DashboardLayout user={user} stats={stats} notifications={notifications} />
}// ✅ Правильно: параллельное получение всех данных
async function Dashboard() {
const [user, stats, notifications] = await Promise.all([
fetchUser(),
fetchStats(),
fetchNotifications(),
])
return <DashboardLayout user={user} stats={stats} notifications={notifications} />
}Правило: server-parallel-fetching (CRITICAL)
Шаг 5: Кеширование повторных вычислений с React.cache
// ❌ Ошибка: повторное вычисление при каждом рендере
async function UserProfile({ userId }: { userId: string }) {
const userData = await fetchUser(userId)
const posts = await fetchUserPosts(userId)
const comments = await fetchUserComments(userId)
return <Dashboard userData={userData} posts={posts} comments={comments} />
}// ✅ Правильно: используем React.cache для кеширования, один и тот же запрос выполняется только один раз
const fetchCachedUser = React.cache(async (userId: string) => {
return await fetchUser(userId)
})
async function UserProfile({ userId }: { userId: string }) {
const userData = await fetchCachedUser(userId)
const posts = await fetchUserPosts(userId) // может повторно использовать userData
const comments = await fetchUserComments(userId)
return <Dashboard userData={userData} posts={posts} comments={comments} />
}Правило: server-cache-react (MEDIUM)
Контрольная точка ✅
После выполнения вышеуказанных шагов проверьте, освоили ли вы:
- [ ] Знать, как запустить AI-анализ производительности React
- [ ] Понимать важность "устранения каскадной загрузки" (уровень CRITICAL)
- [ ] Знать, когда использовать
Promise.all()для параллельных запросов - [ ] Понимать роль динамического импорта (
next/dynamic) - [ ] Знать, как уменьшить ненужные Re-render
- [ ] Понимать роль React.cache на сервере
- [ ] Уметь распознавать проблемы производительности в коде
На что обратить внимание
Проблема 1: Чрезмерная оптимизация
Не оптимизируйте преждевременно
Оптимизируйте только когда действительно есть проблемы производительности. Преждевременное использование useMemo, useCallback может сделать код менее читаемым и может принести отрицательный результат.
Помните:
- Сначала измерьте с помощью React DevTools Profiler
- Сначала решайте проблемы уровней CRITICAL и HIGH
useMemoиспользуйте только когда "вычисления при рендеринге стоят дорого"
Проблема 2: Игнорирование производительности сервера
Особенности Next.js
У Next.js много методов оптимизации сервера (React.cache, parallel fetching, after()), они дают большую отдачу, чем оптимизация клиента.
Приоритет: оптимизация сервера > оптимизация клиента > микрооптимизация
Проблема 3: Добавлять React.memo ко всем компонентам
React.memo не серебряная пуля
React.memo полезен только когда "prop не меняется, но родительский компонент часто обновляется".
Неправильное использование:
- Простые компоненты (время рендеринга < 1ms)
- Компоненты, чьи props часто меняются
- Компоненты, которым нужно реагировать на обновления родительского компонента
Проблема 4: Производное состояние зависит от useEffect
Производное состояние (derived state) должно вычисляться при рендеринге, а не через useEffect + setState.
// ❌ Ошибка: производное состояние через Effect (дополнительный Re-render)
useEffect(() => {
setFiltered(items.filter(...))
}, [items])
// ✅ Правильно: вычисление при рендеринге (ноль дополнительных затрат)
const filtered = items.filter(...)Итоги урока
Ключевые принципы оптимизации производительности React:
- Устранить каскадную загрузку: независимые операции выполняются параллельно с
Promise.all() - Уменьшить размер Bundle: большие компоненты загружаются динамически через
next/dynamic - Уменьшить Re-render: оборачиваем чистые компоненты
React.memo, избегаем ненужных Effect - Приоритет оптимизации сервера:
React.cacheи параллельное получение Next.js дают наибольшую отдачу - Автоматический анализ с AI: позвольте Agent Skills помогать вам находить и исправлять проблемы
57 правил Vercel охватывают все сценарии от архитектуры до микрооптимизации. Научившись запускать AI для применения этих правил, качество вашего кода значительно улучшится.
Следующий урок
Далее мы изучим Аудит руководств по веб-дизайну интерфейсов.
Вы узнаете:
- Как использовать 100+ правил для аудита доступности (a11y)
- Проверка производительности анимации и Focus States
- Аудит валидации форм и поддержки темного режима
Приложение: Справочник по исходному коду
Нажмите, чтобы раскрыть расположение исходного кода
Обновлено: 2026-01-25
| Функция | Путь к файлу | Строки |
|---|---|---|
| Определение навыка лучших практик React | skills/react-best-practices/SKILL.md | Весь файл |
| Полная документация правил | skills/react-best-practices/AGENTS.md | Весь файл |
| 57 файлов правил | skills/react-best-practices/rules/*.md | - |
| Шаблон правила | skills/react-best-practices/rules/_template.md | Весь файл |
| Метаданные | skills/react-best-practices/metadata.json | Весь файл |
| Обзор README | README.md | 9-27 |
Ключевые файлы (примеры правил уровня CRITICAL):
| Правило | Путь к файлу | Описание |
|---|---|---|
| Параллельные запросы Promise.all() | async-parallel.md | Устранение каскадной загрузки |
| Динамический импорт больших компонентов | bundle-dynamic-imports.md | Уменьшение размера Bundle |
| Defer await | async-defer-await.md | Отложенное выполнение асинхронных операций |
Ключевые константы:
version = "1.0.0": версия библиотеки правил (metadata.json)organization = "Vercel Engineering": поддерживающая организация
8 категорий правил:
async-(устранение каскадной загрузки, 5 правил, CRITICAL)bundle-(оптимизация сборки, 5 правил, CRITICAL)server-(производительность сервера, 7 правил, HIGH)client-(получение данных на клиенте, 4 правила, MEDIUM-HIGH)rerender-(оптимизация повторного рендеринга, 12 правил, MEDIUM)rendering-(производительность рендеринга, 9 правил, MEDIUM)js-(производительность JavaScript, 12 правил, LOW-MEDIUM)advanced-(расширенные шаблоны, 3 правила, LOW)