Назад к блогу
Разработка

Next.js 14: Оптимизация производительности

7 проверенных способов ускорить ваше Next.js приложение и улучшить Core Web Vitals.

28 октября 2025 г.
12 мин чтения
65 просмотров
MOLOTILO

MOLOTILO DIGITAL

Next.js 14: Оптимизация производительности

Почему производительность важна

Скорость загрузки напрямую влияет на конверсию. По данным Google, увеличение времени загрузки с 1 до 3 секунд повышает вероятность отказа на 32%. Next.js 14 предоставляет мощные инструменты для оптимизации.

1. App Router и Server Components

App Router в Next.js 14 использует React Server Components по умолчанию:

// app/products/page.tsx - Server Component
import { getProducts } from '@/lib/api';
import ProductCard from '@/components/ProductCard';

export default async function ProductsPage() {
  const products = await getProducts();
  
  return (
    <div className="grid grid-cols-3 gap-6">
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

// components/AddToCartButton.tsx - Client Component
'use client';

import { useState } from 'react';

export function AddToCartButton({ productId }: { productId: string }) {
  const [loading, setLoading] = useState(false);
  
  const handleClick = async () => {
    setLoading(true);
    await addToCart(productId);
    setLoading(false);
  };
  
  return (
    <button onClick={handleClick} disabled={loading}>
      {loading ? 'Добавление...' : 'В корзину'}
    </button>
  );
}

2. Оптимизация изображений

import Image from 'next/image';

// ✅ Автоматическая оптимизация
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
  placeholder="blur"
/>

// ✅ Адаптивные изображения
<Image
  src="/product.jpg"
  alt="Product"
  fill
  sizes="(max-width: 768px) 100vw, 50vw"
  className="object-cover"
/>

3. Streaming и Suspense

import { Suspense } from 'react';
import { Skeleton } from '@/components/ui/Skeleton';

export default function DashboardPage() {
  return (
    <div className="grid grid-cols-2 gap-6">
      <h1>Панель управления</h1>
      
      <Suspense fallback={<Skeleton className="h-64" />}>
        <Analytics />
      </Suspense>
      
      <Suspense fallback={<Skeleton className="h-96" />}>
        <RecentOrders />
      </Suspense>
    </div>
  );
}

4. Кэширование данных

// Кэширование по умолчанию
async function getProducts() {
  const res = await fetch('https://api.example.com/products');
  return res.json();
}

// Ревалидация по времени
async function getNews() {
  const res = await fetch('https://api.example.com/news', {
    next: { revalidate: 3600 }
  });
  return res.json();
}

// Без кэширования
async function getCart() {
  const res = await fetch('https://api.example.com/cart', {
    cache: 'no-store'
  });
  return res.json();
}

// Инвалидация кэша
import { revalidateTag, revalidatePath } from 'next/cache';

export async function updateProduct(id: string, data: ProductData) {
  await db.product.update({ where: { id }, data });
  revalidateTag(`product-${id}`);
  revalidatePath('/products');
}

5. Параллельная загрузка данных

// ❌ Последовательно — 750ms
async function Page() {
  const user = await getUser();     // 200ms
  const posts = await getPosts();   // 300ms
  const comments = await getComments(); // 250ms
}

// ✅ Параллельно — 300ms
async function Page() {
  const [user, posts, comments] = await Promise.all([
    getUser(),
    getPosts(),
    getComments()
  ]);
}

6. Динамический импорт

import dynamic from 'next/dynamic';

const Chart = dynamic(() => import('@/components/Chart'), {
  loading: () => <ChartSkeleton />,
  ssr: false
});

const Modal = dynamic(() => import('@/components/Modal'));

export function Dashboard() {
  const [showModal, setShowModal] = useState(false);
  
  return (
    <>
      <Chart data={chartData} />
      {showModal && <Modal onClose={() => setShowModal(false)} />}
    </>
  );
}

7. Оптимизация шрифтов

import { Inter, JetBrains_Mono } from 'next/font/google';

const inter = Inter({
  subsets: ['latin', 'cyrillic'],
  display: 'swap',
  variable: '--font-inter',
});

export default function RootLayout({ children }) {
  return (
    <html className={inter.variable}>
      <body>{children}</body>
    </html>
  );
}

SSG, ISR и SSR — когда что использовать

Next.js предлагает три стратегии рендеринга:

  • SSG (Static Site Generation) — страницы генерируются при сборке. Идеально для блогов и документации.
  • ISR (Incremental Static Regeneration) — статические страницы обновляются по таймеру. Баланс между скоростью и актуальностью.
  • SSR (Server-Side Rendering) — страницы генерируются при каждом запросе. Для персонализированного контента.

Метрики Core Web Vitals

Google использует три ключевые метрики для оценки производительности:

  • LCP (Largest Contentful Paint) — время загрузки главного контента. Цель: менее 2.5 секунд.
  • FCP (First Contentful Paint) — время до первого отображения контента.
  • TTI (Time to Interactive) — время до полной интерактивности страницы.

Lazy Loading и Code Splitting

Разделение bundle на части (code splitting) и ленивая загрузка (lazy loading) критически важны для производительности. Next.js делает это автоматически для страниц, но компоненты нужно оптимизировать вручную через dynamic imports.

Заключение

Применяя эти оптимизации, вы можете значительно улучшить Core Web Vitals вашего приложения. Начните с Server Components и оптимизации изображений — это даст наибольший эффект при минимальных усилиях.

Помните: преждевременная оптимизация — корень всех зол. Сначала измеряйте, потом оптимизируйте.

Next.jsReactPerformance

Понравилась статья?

Подпишитесь на наш блог, чтобы не пропустить новые материалы