Урок 09

Оптимизация

Next.js даёт встроенные инструменты для оптимизации.

Изображения

import Image from 'next/image';

<Image
    src="/hero.jpg"
    alt="Hero"
    width={1200}
    height={600}
    priority
/>

Автоматически:

  • Конвертирует в WebP/AVIF
  • Ресайзит под экран
  • Ленивая загрузка
  • Предотвращает layout shift

Локальные изображения

import hero from '@/public/hero.jpg';

<Image src={hero} alt="Hero" placeholder="blur" />

Импорт даёт размеры автоматически.

Внешние изображения

next.config.ts:

const nextConfig = {
    images: {
        remotePatterns: [
            {
                protocol: 'https',
                hostname: 'example.com',
            },
        ],
    },
};

Шрифты

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

const inter = Inter({ subsets: ['latin'] });

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

Плюсы:

  • Self-hosting — без запросов к Google
  • Без layout shift
  • Автоматический subset

Локальные:

import localFont from 'next/font/local';

const myFont = localFont({ src: './my-font.woff2' });

Скрипты

import Script from 'next/script';

<Script
    src="https://analytics.example.com/script.js"
    strategy="afterInteractive"
/>

Стратегии:

  • beforeInteractive — до интерактива
  • afterInteractive — после (по умолчанию)
  • lazyOnload — при простое
  • worker — в web worker

Динамические импорты

import dynamic from 'next/dynamic';

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

Компонент грузится только при использовании.

Анализ бандла

npm install @next/bundle-analyzer

next.config.ts:

import bundleAnalyzer from '@next/bundle-analyzer';

const withBundleAnalyzer = bundleAnalyzer({
    enabled: process.env.ANALYZE === 'true',
});

export default withBundleAnalyzer({});
ANALYZE=true npm run build

Package imports

Оптимизация импортов тяжёлых библиотек:

const nextConfig = {
    experimental: {
        optimizePackageImports: ['lucide-react', '@mui/material'],
    },
};

Turbopack

Встроен в Next.js 16. Быстрее Webpack, включён по умолчанию в dev.

Кеширование fetch

fetch(url, { cache: 'force-cache' }); // кеш
fetch(url, { cache: 'no-store' });    // без кеша
fetch(url, { next: { revalidate: 60 } }); // ISR

Static vs Dynamic

  • Static — если нет динамики, рендерится на этапе сборки
  • Dynamic — если есть cookies(), headers(), searchParams

Статические страницы быстрее.

Partial Prerendering

Экспериментально. Статическая оболочка + динамические части:

export const experimental_ppr = true;

Итоги

  • next/image — оптимизация картинок
  • next/font — шрифты без layout shift
  • next/script — контроль загрузки
  • dynamic для ленивых компонентов
  • Анализ бандла
  • Кеш fetch и ISR