Next.jsSeniorExperience

Как понять, что проблема в проекте связана с Next.js, а не с API, сетью, дизайном состояния или плохой архитектурой?

Изолируйте проблему последовательно: замените реальный API мок-данными, проверьте Server/Client Component границу, протестируйте API независимо через curl, проверьте кеш и состояние данных.

Как изолировать проблему Next.js от внешних причин

Диагностика начинается с формулировки гипотезы: что конкретно сломано — рендеринг, маршрутизация, стили, данные, производительность? Затем систематически исключаются внешние факторы.

Шаг 1: воспроизвести в минимальном окружении

Создайте тест-кейс, убрав API и бизнес-логику:

// Вместо реального fetch попробуйте хардкод
export default async function Page() {
  // const data = await fetch("https://api.example.com/data");
  const data = { title: "Test" }; // мок
  return <h1>{data.title}</h1>;
}

Если с моком работает — проблема в API или сети, а не в Next.js.

Шаг 2: разделить Server и Client

Ошибки, которые выглядят как «Next.js сломал компонент», часто являются нарушением Server/Client границы:

  • Использование window, localStorage в Server Component — TypeError в runtime.
  • Передача функции как prop через границу — ошибка сериализации.
  • Импорт серверного модуля (с "use server") в клиентский код.
# Проверить, что именно сервер/клиент граница
npx next build 2>&1 | grep "Error"

Шаг 3: проверить API независимо

curl -s https://api.example.com/endpoint | jq .
# или
wrk -t4 -c100 -d10s https://api.example.com/endpoint

Если API отвечает медленно или с ошибками вне Next.js — проблема не во фреймворке.

Шаг 4: проверить сеть и кеш

  • Stale данные в браузере — проверить Network tab, смотреть на статус 304 vs 200 и заголовки Cache-Control.
  • Stale данные в Next.js кеше — попробовать fetch(url, { cache: "no-store" }) и посмотреть, изменится ли поведение.
  • CDN кеш — проверить заголовки x-vercel-cache, x-cache и попробовать запрос с другого IP/региона.

Шаг 5: проверить состояние данных

Часто «баг Next.js» — это неправильная инициализация стора или race condition в useEffect:

"use client";
import { useEffect, useState } from "react";

export function UserProfile({ userId }: { userId: string }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Если userId меняется быстро — старый fetch перезапишет новый
    let cancelled = false;
    fetch(`/api/users/${userId}`)
      .then(r => r.json())
      .then(data => { if (!cancelled) setUser(data); });
    return () => { cancelled = true; };
  }, [userId]);

  return <div>{user?.name}</div>;
}

Индикаторы, что проблема именно в Next.js

  • Проблема воспроизводится с мок-данными (без реального API).
  • Поведение отличается между next dev и next start (production build).
  • Ошибка связана с гидрацией: «Hydration failed because the server rendered HTML didn't match».
  • Проблема с маршрутизацией: неправильный URL, неверный layout, не срабатывает loading.tsx.
  • Статические файлы не обновляются после ребилда — проблема с ISR или revalidatePath.

Подводные камни

  • Ошибка гидрации часто не в Next.js, а в коде, который использует Math.random(), Date.now() или window напрямую в render — сервер и клиент дают разные значения.
  • Разница поведения next dev vs production: в dev-режиме компоненты рендерятся дважды (StrictMode), кеш не работает как в production — это не баг Next.js.
  • Обвинять фреймворк в медленной работе без профилирования — самая частая ошибка: 90% проблем с производительностью Next.js-приложений — это N+1 запросы к БД или отсутствие индексов.
  • Middleware-ошибки выглядят как 500 от Next.js, но причина — в Edge Runtime ограничениях (нет Node.js API). Проверяйте логи функции, а не сервера.
  • Кастомный _app.tsx (Pages Router) в App Router не работает — нужен layout.tsx. Перепутать их легко при миграции.
  • Сообщения об ошибках Next.js иногда указывают на симптом, а не причину. Всегда смотрите полный stack trace в серверных логах контейнера, а не только в браузере.

What hurts your answer

  • Сразу обвинять Next.js, не проверив соседние слои системы
  • Чинить симптом без минимального воспроизведения и evidence
  • Не учитывать версии, конфигурацию, окружение и recent changes

What they're listening for

  • Умеет локализовать проблему вокруг Next.js
  • Двигается от симптома к гипотезам и проверкам
  • Отличает баг инструмента от ошибки использования или окружения

Related topics