1. Server Actions и API Routes в Next.js 15
Next.js 15 — это не просто ещё одна версия популярного фреймворка, а целый новый взгляд на архитектуру современных React-приложений. В нём появилось сразу два способа работы с серверным кодом:
- API Routes (Route Handlers) — классический способ организации серверных эндпоинтов. Вы пишете файлы route.ts (или .js) в папке app/api, и эти файлы становятся доступны по HTTP, как обычные REST API.
- Server Actions — новый подход, позволяющий вызывать серверные функции напрямую из компонентов, без явных fetch-запросов, через <form action={serverAction}> или программно.
Казалось бы, зачем нам две разные системы? Всё дело в удобстве и сценариях использования.
Как работают API Routes (Route Handlers)
Сначала немного повторения из прошлых лекций.
API Routes (или Route Handlers) — это обработчики HTTP-запросов, которые живут в папке app/api. Каждый такой файл экспортирует асинхронную функцию для одного или нескольких HTTP-методов:
// app/api/todos/route.ts
import { NextResponse } from 'next/server';
export async function GET(request) {
// Получить список задач
return NextResponse.json([{ id: 1, title: 'Учить Next.js' }]);
}
export async function POST(request) {
// Добавить новую задачу
const data = await request.json();
// ...логика сохранения
return NextResponse.json({ success: true }, { status: 201 });
}
Кратко:
- Можно обрабатывать любые HTTP-методы.
- Работает как обычный API: fetch-запросы, сторонние клиенты, Postman — всё доступно.
- Подходит для интеграции с внешними сервисами, мобильными приложениями, сторонними фронтендами.
2. Как работают Server Actions
Server Actions — это новый способ вызывать серверный код напрямую из React-компонентов, не задумываясь о ручных fetch-запросах. Вы определяете функцию с директивой "use server", и Next.js сам организует передачу данных между клиентом и сервером.
// app/actions/todoActions.ts
'use server';
export async function addTodo(formData) {
const title = formData.get('title');
// ...логика добавления задачи
}
В компоненте:
import { addTodo } from '../actions/todoActions';
export default function TodoForm() {
return (
<form action={addTodo}>
<input type="text" name="title" />
<button type="submit">Добавить</button>
</form>
);
}
Кратко:
- Не нужно писать отдельный fetch.
- Нет явного API-эндпоинта — функция вызывается как бы "изнутри" Next.js.
- Удобно для простых форм, мутаций, когда не требуется интеграция с внешними клиентами.
3. Отличия Server Actions и API Routes (Route Handlers)
Давайте разложим по полочкам и сравним два подхода.
| Характеристика | API Routes (Route Handlers) | Server Actions |
|---|---|---|
| Вызов из браузера | Через fetch, axios и т.д. | Через <form action={...}> или программно (React) |
| Доступность извне | Доступны по HTTP любому клиенту | Только из Next.js компонентов |
| Архитектура | Явные REST/HTTP эндпоинты | Серверные функции |
| Обработка данных | req.json(), req.body, req.query | formData (или параметры) |
| Поддержка методов | GET, POST, PUT, DELETE и др. | Обычно POST (мутации) |
| Валидация, авторизация | Любая, вручную | Аналогично, но проще интегрировать с формами |
| Интеграция с внешним | Да (мобильные, сторонние клиенты) | Нет |
В чём фундаментальная разница?
- API Routes — это полноценные HTTP-эндпоинты, которые можно дергать из любого места (даже из curl или Postman).
- Server Actions — это "приватные" серверные функции, которые доступны только вашему Next.js-приложению, и только через формы/компоненты.
Аналогия
- API Routes — как дверь в ваш дом: через неё могут войти и вы, и гости, и курьер, и даже соседский кот (если знает адрес).
- Server Actions — как потайной ход, ведущий только в вашу комнату, и только вы знаете, где он находится.
4. Когда использовать Server Actions
Server Actions отлично подходят для:
- Обработки форм: когда пользователь что-то отправляет, и вы хотите сразу обработать данные на сервере.
- Мутаций данных: добавление, изменение, удаление (например, добавить задачу, удалить комментарий).
- Внутренней бизнес-логики: когда не требуется внешний доступ к API.
- Минимизации boilerplate: меньше кода, не нужно писать fetch, не нужно думать о маршрутах.
Пример:
Вы делаете TODO-приложение, где пользователь может добавить задачу через форму. Используйте Server Action:
<form action={addTodo}>
<input name="title" />
<button>Добавить</button>
</form>
Всё — никаких fetch, никаких ручных API-запросов.
5. Когда использовать API Routes (Route Handlers)
API Routes (Route Handlers) нужны, когда:
- Нужен внешний API: ваше приложение должно быть доступно мобильным клиентам, другим фронтендам, интеграциям.
- Требуется поддержка разных HTTP-методов: например, GET для получения данных, PUT/DELETE для обновления/удаления.
- Требуется сложная маршрутизация: например, /api/users/[id].
- Нужно реализовать REST или GraphQL API для сторонних клиентов.
- Вам нужно разделить серверную логику и фронтенд: например, когда фронтенд и бэкенд разрабатывают разные команды.
Пример:
У вас есть мобильное приложение, которое должно получать и отправлять данные на сервер. Вы реализуете API Routes, чтобы ваше Next.js-приложение выступало как полноценный сервер.
6. Как Server Actions и API Routes могут работать вместе
В реальных проектах часто используются оба подхода.
Пример сценария:
- Для пользовательских форм и внутренней логики используете Server Actions.
- Для интеграций с внешними сервисами или мобильными приложениями — API Routes.
Можно даже вызывать API Routes из Server Actions, если нужно переиспользовать бизнес-логику, или наоборот.
Пример: Server Action вызывает API Route
// app/actions/addUser.ts
'use server';
export async function addUser(formData) {
const name = formData.get('name');
// Вызываем API Route через fetch (локально)
const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/users`, {
method: 'POST',
body: JSON.stringify({ name }),
headers: { 'Content-Type': 'application/json' }
});
return await res.json();
}
Пример: API Route использует бизнес-логику из Server Action
Можно вынести бизнес-логику в отдельный модуль и импортировать её и в API Route, и в Server Action.
// app/lib/userService.ts
export async function createUser(name) {
// ...добавление пользователя в БД
}
// app/api/users/route.ts
import { createUser } from '../../lib/userService';
export async function POST(request) {
const { name } = await request.json();
await createUser(name);
return NextResponse.json({ success: true });
}
// app/actions/addUser.ts
'use server';
import { createUser } from '../lib/userService';
export async function addUser(formData) {
const name = formData.get('name');
await createUser(name);
}
7. Практические рекомендации: что выбрать?
Когда лучше Server Actions:
- Вся логика внутри вашего Next.js-приложения.
- Нет необходимости открывать API вовне.
- Нужно просто и быстро обработать форму.
- Вы хотите использовать преимущества Server Components (минимизация клиентского JS, SSR).
Когда лучше API Routes:
- Требуется внешний API.
- Нужно поддерживать разные HTTP-методы.
- Необходимо масштабировать серверную часть отдельно от фронта.
- Используется сторонний клиент (например, мобильное приложение).
Можно ли использовать только Server Actions?
Если вы разрабатываете только веб-приложение на Next.js, и не планируете открывать API для внешних клиентов — да, можно! Но если есть хотя бы малейший шанс, что API понадобится другим приложениям — лучше сразу проектировать логику через Route Handlers.
8. Типичные ошибки при выборе между Server Actions и API Routes
Ошибка №1: попытка вызвать Server Action из внешнего клиента.
Server Actions доступны только из компонентов Next.js. Если вы попробуете сделать fetch на Server Action — ничего не получится, она не "открыта" наружу.
Ошибка №2: избыточное дублирование кода.
Если бизнес-логика реализована и в Server Action, и в API Route, не копируйте её — выносите в отдельный модуль и переиспользуйте.
Ошибка №3: использование Server Actions для публичных API.
Если нужно, чтобы API был доступен снаружи (например, для мобильного приложения), используйте Route Handlers.
Ошибка №4: попытка использовать GET-запросы с Server Actions.
Server Actions ориентированы на мутации (POST), для получения данных используйте Server Components или API Routes.
Ошибка №5: смешивание клиентского и серверного кода.
Не пытайтесь импортировать Server Action в Client Component без use server — получите ошибку компиляции.
Ошибка №6: забыли про ограничения Server Actions.
Server Actions нельзя вызывать из fetch, нельзя использовать для SSR данных, которые должны быть доступны по прямому HTTP-запросу.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ