Next.js: обзор

Next.js — React-фреймворк с поддержкой SSR, SSG, ISR и CSR, файловой маршрутизацией и встроенной оптимизацией, позволяющий строить полноценные веб-приложения без настройки сборщика.

Зачем нужно

Create React App создаёт чистый CSR, а значит — проблемы с SEO, медленный FCP, отсутствие серверной части. Next.js решает всё это из коробки: выбор стратегии рендеринга на уровне маршрута, автоматическое разделение кода, оптимизация изображений, API-роуты. Для большинства production React-приложений Next.js — стандартный выбор.

Где используется

  • E-commerce с SEO (страницы товаров через SSG/ISR)
  • Корпоративные сайты и лендинги
  • Fullstack-приложения с API Routes
  • SaaS-продукты (дашборды через CSR, публичные страницы через SSR/SSG)

Файловая маршрутизация

app/                          ← App Router (Next.js 13+)
  layout.tsx                  ← корневой layout
  page.tsx                    ← маршрут /
  about/
    page.tsx                  ← маршрут /about
  blog/
    [slug]/
      page.tsx                ← маршрут /blog/:slug
  api/
    users/
      route.ts                ← API endpoint /api/users

pages/                        ← Pages Router (классический)
  index.tsx                   ← /
  about.tsx                   ← /about
  blog/[slug].tsx             ← /blog/:slug
  api/users.ts                ← /api/users

App Router: Server Components по умолчанию

// app/blog/[slug]/page.tsx
// Это Server Component — рендерится на сервере, не отправляет JS клиенту

type Props = {
  params: { slug: string };
};

async function BlogPost({ params }: Props) {
  // fetch напрямую в компоненте — работает в Server Components
  const post = await fetch(`https://api.example.com/posts/${params.slug}`)
    .then(r => r.json());

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

export default BlogPost;

// Метаданные для SEO
export async function generateMetadata({ params }: Props) {
  const post = await fetchPost(params.slug);
  return { title: post.title, description: post.excerpt };
}

API Routes

// app/api/users/route.ts (App Router)
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const users = await db.users.findAll;
  return NextResponse.json(users);
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  const user = await db.users.create(body);
  return NextResponse.json(user, { status: 201 });
}

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

import Image from 'next/image';

function ProductCard({ product }) {
  return (
    <div>
      {/* next/image: lazy loading, WebP, правильные размеры */}
      <Image
        src={product.imageUrl}
        alt={product.name}
        width={400}
        height={300}
        priority={false} // priority: true для hero-изображений
      />
    </div>
  );
}

Частые ошибки

  • Используют useEffect для загрузки данных в Server Components — Server Components — async функции, данные загружаются напрямую через await fetch.
  • Смешивают App Router и Pages Router — у них разные соглашения; не переносите паттерны из одного в другой.
  • Не кэшируют fetch в Server Components — Next.js автоматически дедуплицирует и кэширует fetch; используйте опцию { cache: 'no-store' } только для данных реального времени.
  • Client Components без 'use client' — интерактивные компоненты (хуки, события) требуют директивы 'use client' в начале файла.

Связанные темы

Ресурсы