1. NextResponse.json(): возвращаем JSON-ответ
NextResponse — это специальный класс, который расширяет стандартный API Response и добавляет удобные методы для работы с ответами в Next.js. Его цель — сделать формирование ответа простым, безопасным и совместимым со всеми особенностями Next.js (например, с middleware, SSR, кешированием и т.д.).
В Route Handlers (файлы app/api/route.ts или app/api/route.js) вы обычно возвращаете объект типа Response или NextResponse. Если вы возвращаете просто строку, Next.js сам обернёт её в Response. Но если вы хотите контролировать формат, заголовки, статус-код или прокидывать запрос дальше, используйте NextResponse.
Синтаксис
import { NextResponse } from 'next/server';
return NextResponse.json(data, options?);
- data — любой сериализуемый в JSON объект (обычно это объект или массив).
- options (необязательно) — объект с дополнительными параметрами (например, статус-код, заголовки).
Простой пример
Допустим, у нас есть API-эндпоинт, который возвращает список задач:
// app/api/todos/route.js
import { NextResponse } from 'next/server';
export async function GET(request) {
const todos = [
{ id: 1, title: 'Купить хлеб', completed: false },
{ id: 2, title: 'Выучить Next.js', completed: true },
];
return NextResponse.json(todos);
}
Когда клиент отправляет GET-запрос на /api/todos, он получит такой JSON:
[
{ "id": 1, "title": "Купить хлеб", "completed": false },
{ "id": 2, "title": "Выучить Next.js", "completed": true }
]
Автоматические заголовки
NextResponse.json() сам выставляет необходимые заголовки:
- Content-Type: application/json; charset=utf-8
- Корректно сериализует данные
Добавление статус-кода
По умолчанию статус-код будет 200 OK. Если нужно другой статус, используйте второй аргумент:
return NextResponse.json(
{ error: 'Not found' },
{ status: 404 }
);
Добавление заголовков
return NextResponse.json(
{ message: 'Created' },
{
status: 201,
headers: {
'X-Custom-Header': 'Hello!',
},
}
);
Пример: создание задачи (POST)
// app/api/todos/route.js
import { NextResponse } from 'next/server';
export async function POST(request) {
const body = await request.json();
// Здесь обычно добавление в БД, но мы просто возвращаем то, что получили
return NextResponse.json(
{ id: Date.now(), ...body },
{ status: 201 }
);
}
2. NextResponse.next(): прокидываем запрос дальше
Где применяется?
- В middleware (например, middleware.ts)
- В сложных сценариях, когда нужно пропустить запрос дальше по цепочке
Пример: middleware, который логирует запросы
// middleware.ts
import { NextResponse } from 'next/server';
export function middleware(request) {
console.log('Запрос на:', request.nextUrl.pathname);
// Передаём запрос дальше (к следующему обработчику)
return NextResponse.next();
}
Если вы вернёте NextResponse.next(), Next.js продолжит обработку запроса (например, дойдёт до Route Handler или страницы).
Важно! В Route Handlers (файлы в app/api/route.js) NextResponse.next() обычно не используют, потому что там вы должны вернуть финальный ответ. Но если вдруг вы строите кастомные цепочки обработки (например, через middleware), этот метод вам пригодится.
3. Практические примеры: полноценный API-эндпоинт
// app/api/todos/route.js
import { NextResponse } from 'next/server';
// Имитация базы данных в памяти (для примера)
const todos = [
{ id: 1, title: 'Погладить кота', completed: false },
{ id: 2, title: 'Сделать домашку', completed: false },
];
// GET — получить все задачи
export async function GET(request) {
return NextResponse.json(todos);
}
// POST — добавить новую задачу
export async function POST(request) {
const body = await request.json();
const newTodo = {
id: todos.length + 1,
title: body.title || 'Без названия',
completed: false,
};
todos.push(newTodo);
return NextResponse.json(newTodo, { status: 201 });
}
Пояснения:
Для GET мы просто возвращаем массив задач.
Для POST разбираем тело запроса, создаём новую задачу, добавляем в массив и возвращаем её клиенту с кодом 201 (Created).
4. Как формировать разные типы ответов
Ошибка (например, задача не найдена)
export async function GET(request) {
// ... поиск задачи
if (!todo) {
return NextResponse.json(
{ error: 'Задача не найдена' },
{ status: 404 }
);
}
return NextResponse.json(todo);
}
Успех без данных (например, удаление задачи)
export async function DELETE(request) {
// ... удалили задачу
return NextResponse.json(
{ message: 'Задача удалена' },
{ status: 200 }
);
}
Кастомные заголовки
return NextResponse.json(
{ data: 'OK' },
{ headers: { 'X-API-Version': '1.0.0' } }
);
5. Сравнение NextResponse.json() и обычного Response
Можно возвращать и стандартный Response:
return new Response(JSON.stringify(data), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
Но!
- NextResponse.json() делает всё это за вас автоматически.
- Гарантирует совместимость с Next.js (например, для middleware, кеширования, Edge Runtime).
- Код лаконичнее и меньше шансов ошибиться с заголовками.
Совет: Используйте NextResponse.json() для JSON-ответов — это best practice.
6. Типичные ошибки при формировании ответа
Ошибка №1: забыли выставить статус-код
Если не указать статус явно, по умолчанию будет 200. Иногда забывают выставить 201 для создания или 404 для ошибки, и клиент не понимает, что произошло.
Ошибка №2: возвращаете не сериализуемый объект
NextResponse.json() не сможет сериализовать, например, функцию, класс или объект с circular reference. Всегда возвращайте только простые объекты, массивы, числа, строки, булевы значения.
Ошибка №3: не тот Content-Type
Если используете обычный Response, можно забыть указать Content-Type: application/json, и клиент не сможет корректно обработать ответ. NextResponse.json() делает это за вас.
Ошибка №4: используете NextResponse.next() вместо финального ответа
В Route Handler всегда нужно возвращать финальный ответ (NextResponse.json(), строку, Response и т.д.), а не NextResponse.next(). Последний нужен только для middleware.
Ошибка №5: не await-ите request.json()
Если забыть await при чтении тела запроса, получите Promise вместо данных, что приведёт к ошибкам.
// Ошибка:
const body = request.json(); // body — Promise!
// Правильно:
const body = await request.json();
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ