← Назад к вопросам
Как оптимизировать первый рендер страницы?
2.2 Middle🔥 181 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Критические операции для первого рендера
Первый рендер (First Contentful Paint, FCP) критичен для пользовательского опыта. Есть несколько основных стратегий оптимизации.
1. Code Splitting и ленивая загрузка
// ПЛОХО: Загружаем весь код сразу
import HeavyComponent from './HeavyComponent';
export function App() {
return <HeavyComponent />;
}
// ХОРОШО: Загружаем компонент только когда нужно
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(
() => import('./HeavyComponent'),
{
loading: () => <div>Loading...</div>,
ssr: false // Не рендерим на сервере
}
);
export function App() {
return <HeavyComponent />;
}
2. Image Optimization
// ПЛОХО: Обычные img теги
export function Hero() {
return <img src="/hero.jpg" alt="Hero" />;
}
// ХОРОШО: Next.js Image компонент
import Image from 'next/image';
export function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // Загружаем критичные изображения первыми
sizes="(max-width: 768px) 100vw, 50vw"
/>
);
}
3. Минимизация JavaScript
// ПЛОХО: Большой bundle
import * as lodash from 'lodash';
const items = lodash.sortBy(data, 'name');
// ХОРОШО: Импортируем только нужное
import sortBy from 'lodash/sortBy';
const items = sortBy(data, 'name');
// ЛУЧШЕ: Используем встроенные методы JavaScript
const items = [...data].sort((a, b) => a.name.localeCompare(b.name));
4. Критический CSS
// Инлайним критичный CSS для выше сгиба контента
// next.config.js
module.exports = {
experimental: {
optimizeCss: true, // Включаем оптимизацию CSS
},
};
// Используем критичные стили напрямую
export function Header() {
return (
<style>{`
.header {
display: flex;
justify-content: space-between;
padding: 1rem;
background: white;
}
`}</style>
);
}
5. Предзагрузка ресурсов
// В Next.js layout или компоненте
import Link from 'next/link';
export function Navigation() {
return (
<>
<Link href="/posts" prefetch={true}>
Posts
</Link>
<Link href="/about">About</Link>
</>
);
}
// Вручную предзагружаем ресурсы
export function Head() {
return (
<>
<link rel="preload" as="script" href="/script.js" />
<link rel="prefetch" href="/api/data" />
<link rel="dns-prefetch" href="https://external-api.com" />
</>
);
}
6. Server-Side Rendering (SSR) и Static Generation
// ПЛОХО: Рендеримся только на клиенте
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data').then(r => r.json()).then(setData);
}, []);
return <div>{data?.title}</div>;
}
// ХОРОШО: Static Generation (самый быстрый вариант)
export async function getStaticProps() {
const data = await fetch('https://api.example.com/data');
return {
props: { data },
revalidate: 3600 // Переиндексируем каждый час
};
}
export default function Page({ data }) {
return <div>{data.title}</div>;
}
// АЛЬТЕРНАТИВА: Server-Side Rendering
export async function getServerSideProps() {
const data = await fetch('https://api.example.com/data');
return {
props: { data },
revalidate: 60
};
}
7. Мемоизация компонентов
// ПЛОХО: Пересчитываем на каждый рендер
export function ExpensiveComponent({ items }) {
const sorted = items.sort((a, b) => a.value - b.value);
return <div>{sorted.map(i => <div key={i.id}>{i.value}</div>)}</div>;
}
// ХОРОШО: Мемоизируем
import { memo, useMemo } from 'react';
export const ExpensiveComponent = memo(function({ items }) {
const sorted = useMemo(
() => items.sort((a, b) => a.value - b.value),
[items]
);
return <div>{sorted.map(i => <div key={i.id}>{i.value}</div>)}</div>;
});
8. Минимизация блокирующих скриптов
// ПЛОХО: Скрипт блокирует парсинг HTML
<script src="/analytics.js"></script>
// ХОРОШО: Асинхронная загрузка
<script async src="/analytics.js"></script>
// ЛУЧШЕ: Отложенная загрузка
<script defer src="/analytics.js"></script>
// В Next.js
import Script from 'next/script';
export function App() {
return (
<>
<Script
src="/analytics.js"
strategy="lazyOnload" // Загружаем после интерактивности
/>
</>
);
}
Проверка производительности
// Используем Web Vitals API для мониторинга
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
Комбинация этих стратегий значительно улучшает первый рендер и пользовательский опыт.